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
}
;}