[Function] Reduce Fraction to Lowest Terms

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
FanaticGuru
Posts: 1906
Joined: 30 Sep 2013, 22:25

[Function] Reduce Fraction to Lowest Terms

19 Dec 2013, 19:52

[Function] LowestTerms

This code reduces a fraction to its lowest terms.

The main function is LowestTerms but it uses another function called GCD to find the Greatest Common Divisor which is a useful function by itself.

Code: Select all

;{[Function] LowestTerms
; Fanatic Guru
; 2013 12 19
; Version 1.0
;
; Function to Reduce Fraction to Lowest Terms
;
;------------------------------------------------
;
; Method:
;   LowestTerms(Fraction)
;
;   Parameters:
;   1) {Fraction} 	A string representing a fraction
;
; Example:
; MsgBox % LowestTerms("15/81") ; Returns 5/27

LowestTerms(F)
{
	RegExMatch(F,"(\d*)/(\d*)",Match), N := Match1, D:= Match2
	while X != 1
		X := GCD(N,D), N := N / X, D := D / X
	N := Floor(N), D := Floor(D)
	return N (D!=1 ? "/" D :"")
}

GCD(A, B) 
{
    while B 
	   B := Mod(A|0x0, A:=B)
    return A
}
;}

[Function] LowerTerms

If a fraction does not have a common divisor this function uses approximation to find the closest fraction that does have a common divisor to force a reduction in terms.

It also allows for the passing of a digit size parameter that will use approximations to find the closest fraction with a number of digits equal to or less than the size parameter.

Code: Select all

;{[Function] LowerTerms
; Fanatic Guru
; 2013 12 19
; Version 1.0
;
; Function to Reduce Fraction to Lower Terms
;
;------------------------------------------------
;
; Comment:
; 	If Fraction has no common divisor then approximation
;	will be used to force a common divisor.
;
; Method:
;   LowerTerms(Fraction, Size)
;
;   Parameters:
;   1) {Fraction} 	A string representing a fraction
;   2) {Size}		Maximum number of digits in fraction's numerator or denominator
;					If no Size is passed to function, fraction is reduced to the closest fraction
;					with a common divisor
;   	Optional
;
; Example:
; MsgBox % LowerTerms("16/32")		; Returns 1/2
; MsgBox % LowerTerms("8/33")			; Returns 4/17 by approximation which is slightly closer than 1/4
;								; 8/34 is closer than 8/32
;								; Just as 1/3 is closer to 1/4 than it is to 1/2
; MsgBox % LowerTerms("197/1113",2) 	; Returns 11/62 by approximation with a limit of 2 digits

LowerTerms(F,S:=99)
{
	FormatFloat := A_FormatFloat
	SetFormat, FloatFast, 0.15
	RegExMatch(F,"(\d*)/(\d*)",M), N := M1, D:= M2
	if (!N or !D)
		return
	if  D=1
		return N
	Dec := N / D
	R_S:
	O_N := N, O_D := D 
	R_R:
	X := 0
	T_N := N, T_D := D 
	while X != 1
		X := GCD(N,D), N := N / X, D := D / X
	if (T_D = D and D > 1)
	{
		if T
			((N / D < Dec) ? N += 1 : D += 1)
		else
			((N / D > Dec) ? N -= 1 : D -= 1)
		goto R_R
	}
	if !T
	{
		N_M := Floor(N), D_M := Floor(D), N := O_N, D:= O_D, T := !T
		goto R_R
	}
	N_P := Floor(N), D_P := Floor(D)
	if (StrLen(D_P) <= S and StrLen(D_M) > S)
		N := N_P, D:= D_P
	else if (StrLen(D_M) <= S and StrLen(D_P) > S)
		N := N_M, D:= D_M
	else
	{
		C_P := Abs(Dec - (N_P / D_P))
		C_M := Abs(Dec - (N_M / D_M))
		if (C_P < C_M)
			N := N_P, D:= D_P
		else
			N := N_M, D:= D_M
	}
	if (StrLen(D) > S)
	{
		T := 0
		goto R_S
	}
	SetFormat, FloatFast, %FormatFloat%
	return N (D!=1 ? "/" D :"")
}

GCD(A, B) 
{
    while B 
	   B := Mod(A|0x0, A:=B)
    return A
}
;}

[Function] SetTerms

This function allows you to set a specific term for the denominator of the fraction. The fraction will be rounded to this denominator then reduce to lowest terms. You could round a fraction to the nearest 32th for example.

Code: Select all

;{[Function] SetTerms
; Fanatic Guru
; 2013 12 19
; Version 1.0
;
; Function to Reduce Fraction to Set Terms
;
;------------------------------------------------
;
; Method:
;   SetTerms(Fraction,Precision)
;
;   Parameters:
;   1) {Fraction} 	A string representing a fraction
;   2) {Precision} 	A number that forces denominator to approximate to this term ie. 16 rounds fraction to 16ths 
;				After approximation forced by Precision, fraction will be reduce to lowest terms
;
; Example:
; MsgBox % SetTerms("123/987",16) ; Returns 1/8

SetTerms(F,P:=0)
{
	RegExMatch(F,"(\d*)/(\d*)",M), N := M1, D:= M2
	if P
		N := Round(N / D * P), D := P
	while X != 1
		X := GCD(N,D), N := N / X, D := D / X
	N := Floor(N), D := Floor(D)
	return N (D!=1 ? "/" D :"")
}

GCD(A, B) 
{
    while B 
	   B := Mod(A|0x0, A:=B)
    return A
}
;}
FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
Hotstring Manager - Create and Manage Hotstrings
[Class] WinHook - Create Window Shell Hooks and Window Event Hooks

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: Google [Bot] and 103 guests