Integer Fraction Arithmetic Rules and Functions
Uses arbitrary-precision arithmetic for exact integer values.
PHP Functions by Jay Tanner of Geneva, NY, USA
Double-Click Within Text Area to Select ALL Code
0) {$w=$B; $B=bcMod($GCD,$B); $GCD=$w;} // Reduce (E/F) to lowest terms (G/H) if possible. $G = bcDiv($E, $GCD); $H = bcDiv($F, $GCD); } // Done. return "$G/$H"; } // End of BC_Add_Frac (...) /* ########################################################################### This PHP function performs arbitrary-precision integer fraction subtraction with reduction option. (A/B) - (C/D) = (A*D - B*C) / (B*D) = E/F E = A*D - B*C F = B*D To return the result reduced to lowest terms, set the ReduceFlag to TRUE. The default is FALSE and will return the raw, un-reduced fraction. Reduced = G/H G = E / GCD H = F / GCD GCD = Greatest Common Divisor of both E and F If GCD == 1, then E/F cannot be reduced and G/H = E/F. The fractions may be composed of any signed integers, such as '17/49' or '23/-2871'. ARGUMENTS: $A_B = Signed integer fraction = 'A / B' $C_D = Signed integer fraction = 'C / D' ERRORS: FALSE is returned if any of the arguments are non-numeric. NO DEPENDENCIES ########################################################################### */ function BC_Sub_Frac ($A_B, $C_D, $ReduceFlag=FALSE) { // Read integer fraction argument strings // and strip out ALL spaces from strings. $A_B = Str_Replace(' ', '', trim($A_B)); $C_D = Str_Replace(' ', '', trim($C_D)); // Account for integer arguments and convert to 'X/1' format. if (StrPos($A_B, '/') === FALSE) {$A_B .= '/1';} if (StrPos($C_D, '/') === FALSE) {$C_D .= '/1';} // Parse fraction strings and extract the individual integer values. list($A,$B) = PReg_Split("[\/]", PReg_Replace("/\s+/", ' ', trim($A_B))); list($C,$D) = PReg_Split("[\/]", PReg_Replace("/\s+/", ' ', trim($C_D))); // Remove any redundant white space from arguments. $A = trim($A); $B = trim($B); $C = trim($C); $D = trim($D); // Error if any of the (A, B, C, D) arguments are non-numeric. if ( !Is_Numeric($A) or !Is_Numeric($B) or !Is_Numeric($C) or !Is_Numeric($D) ) {return FALSE;} // Compute numerator and denominator of the subtraction and // return RAW, unreduced signed integer fraction string. $E = bcSub(bcMul($A,$D), bcMul($B,$C)); $F = bcMul($B,$D); // If ReduceFlag === TRUE, then reduce to lowest // terms. Otherwise return raw, unreduced value. if ($ReduceFlag === TRUE) { $A = Str_Replace('-', '', Str_Replace('+', '', $E)); $B = Str_Replace('-', '', Str_Replace('+', '', $F)); if (bcComp($B,$A) < 0) {$w=$B; $B=$A; $GCD=$w;} else {$GCD=$A;} while ($B <> 0) {$w=$B; $B=bcMod($GCD,$B); $GCD=$w;} // Reduce E/F to lowest // terms, if possible. $E = bcDiv($E, $GCD); $F = bcDiv($F, $GCD); } return "$E/$F"; } // End of BC_Sub_Frac (...) /* ########################################################################### This PHP function performs arbitrary-precision integer fraction multipli- cation with reduction option. (A/B) * (C/D) = (A*C) / (B*D) = (E/F) E = A*C F = B*D To return the result reduced to lowest terms, set the ReduceFlag to TRUE. The default is FALSE and will return the raw, un-reduced fraction. Reduced = G/H G = E / GCD H = F / GCD GCD = Greatest Common Divisor of both E and F If GCD == 1, then E/F cannot be reduced and G/H = E/F. The fractions may be composed of any signed integers, such as '48/-130' or '-165/-55'. ARGUMENTS: A_B = Signed integer fraction = 'A / B' C_D = Signed integer fraction = 'C / D' ERRORS: FALSE is returned if any of the arguments are non-numeric. NO DEPENDENCIES ########################################################################### */ function BC_Mul_Frac ($A_B, $C_D, $ReduceFlag=FALSE) { // Read integer fraction argument strings // and strip out ALL spaces from strings. $A_B = Str_Replace(' ', '', trim($A_B)); $C_D = Str_Replace(' ', '', trim($C_D)); // Account for integer arguments and convert to 'X/1' format. if (StrPos($A_B, '/') === FALSE) {$A_B .= '/1';} if (StrPos($C_D, '/') === FALSE) {$C_D .= '/1';} // Parse fraction strings and extract the individual integer values. list($A,$B) = PReg_Split("[\/]", PReg_Replace("/\s+/", ' ', trim($A_B))); list($C,$D) = PReg_Split("[\/]", PReg_Replace("/\s+/", ' ', trim($C_D))); // Remove any redundant white space from arguments. $A = trim($A); $B = trim($B); $C = trim($C); $D = trim($D); // Error if any of the (A, B, C, D) arguments are non-numeric. if ( !Is_Numeric($A) or !Is_Numeric($B) or !Is_Numeric($C) or !Is_Numeric($D) ) {return FALSE;} // Compute numerator and denominator of the multiplication // and return resulting signed integer fraction string. $E = bcMul($A,$C); $F = bcMul($B,$D); // If ReduceFlag === TRUE, then reduce to lowest // terms. Otherwise return raw, unreduced value. if ($ReduceFlag === TRUE) { $A = Str_Replace('-', '', Str_Replace('+', '', $E)); $B = Str_Replace('-', '', Str_Replace('+', '', $F)); if (bcComp($B,$A) < 0) {$w=$B; $B=$A; $GCD=$w;} else {$GCD=$A;} while ($B <> 0) {$w=$B; $B=bcMod($GCD,$B); $GCD=$w;} // Reduce E/F to lowest terms $E = bcDiv($E, $GCD); $F = bcDiv($F, $GCD); } return "$E/$F"; } // End of BC_Mul_Frac (...) /* ########################################################################### This function performs arbitrary-precision signed integer fraction division with reduction option. All computed integers are EXACT values. (A/B) / (C/D) = (A*D) / (B*C) = E/F Raw: E = A*D F = B*C Reduced = G/H G = E/GCD H = F/GCD GCD = Greatest Common Divisor of both E and F If GCD == 1, then E/F cannot be reduced and G/H = E/F. To return results reduced to lowest terms, set the ReduceFlag to TRUE. The default is FALSE and will return the raw, unreduced fraction. The fractions may be composed of any signed integers, such as '3747/-673' or '117/649'. ARGUMENTS: $A_B = Signed integer fraction = 'A/B' = 'A / B' $C_D = Signed integer fraction = 'C/D' = 'C / D' ERRORS: FALSE is returned if any of the arguments are non-numeric. NO DEPENDENCIES ########################################################################### */ function BC_Div_Frac ($A_B, $C_D, $ReduceFlag=FALSE) { // Read integer fraction argument strings // and strip out ALL spaces from strings. $A_B = Str_Replace(' ', '', trim($A_B)); $C_D = Str_Replace(' ', '', trim($C_D)); // Account for integer arguments and convert to 'X/1' format. if (StrPos($A_B, '/') === FALSE) {$A_B .= '/1';} if (StrPos($C_D, '/') === FALSE) {$C_D .= '/1';} // Parse fraction strings and extract the individual integer values. list($A, $B) = PReg_Split("[\/]", PReg_Replace("/\s+/", ' ', $A_B)); list($C, $D) = PReg_Split("[\/]", PReg_Replace("/\s+/", ' ', $C_D)); // Remove any redundant white space from arguments. $A = trim($A); $B = trim($B); $C = trim($C); $D = trim($D); // Error if any of the (A, B, C, D) arguments are non-numeric. if ( !Is_Numeric($A) or !Is_Numeric($B) or !Is_Numeric($C) or !Is_Numeric($D) ) {return FALSE;} // Compute numerator and denominator of the division and // return RAW, unreduced signed integer fraction string. $E = bcMul($A, $D); $F = bcMul($B, $C); // If ReduceFlag === TRUE, then reduce to lowest // terms. Otherwise return raw, unreduced value. if ($ReduceFlag === TRUE) { $A = Str_Replace('-', '', Str_Replace('+', '', $E)); $B = Str_Replace('-', '', Str_Replace('+', '', $F)); if (bcComp($B, $A) < 0) {$w=$B; $B=$A; $GCD=$w;} else {$GCD=$A;} while ($B <> 0) {$w=$B; $B=bcMod($GCD, $B); $GCD=$w;} // Reduce E/F to lowest // terms, if possible. $E = bcDiv($E, $GCD); $F = bcDiv($F, $GCD); } return "$E/$F"; } // End of BC_Div_Frac (...) ?>