Code: Select all
<?php
class Fraction
{
var $_numerator;
var $_denominator;
function Fraction($numerator, $denominator) {
if ($denominator == 0) {
trigger_error('Denominator cannot be zero', E_USER_WARNING);
return;
}
$this->_numerator = (int) $numerator;
$this->_denominator = (int) $denominator;
}
function &add(&$fraction) {
$num1 = $this->getNumerator();
$num2 = $fraction->getNumerator();
$den1 = $this->getDenominator();
$den2 = $fraction->getDenominator();
$den = $den1 * $den2;
$num = $num1 * $den2 + $num2 * $den1;
$fraction =& new Fraction($num, $den);
$fraction->reduce();
return $fraction;
}
function &subtract(&$fraction) {
return $this->add($fraction->getNegative());
}
function &multiply(&$fraction) {
$num1 = $this->getNumerator();
$num2 = $fraction->getNumerator();
$den1 = $this->getDenominator();
$den2 = $fraction->getDenominator();
$den = $den1 * $den2;
$num = $num1 * $num2;
$fraction =& new Fraction($num, $den);
$fraction->reduce();
return $fraction;
}
function ÷(&$fraction) {
return $this->multiply($fraction->getReciprocal());
}
function reduce() {
if (!$this->isReducible()) {
return;
}
$num = $this->getNumerator();
$den = $this->getDenominator();
if ($num === 0) {
$this->setDenominator(1);
return;
}
if (($num < 0 && $den < 0) || $den < 0) {
$num = -$num;
$den = -$den;
}
$gcf = $this->gcd(abs($num),abs($den));
if ($gcf != 1) {
$num = floor($num / $gcf);
$den = floor($den / $gcf);
}
$this->setNumerator($num);
$this->setDenominator($den);
}
function isReducible() {
$num = $this->getNumerator();
$den = $this->getDenominator();
return ($num == 0 && $den !== 1) // for zero, 0/1 is best
|| (($num < 0 && $den < 0) || $den < 0) //test if both are negative
|| !(($num % $den) && ($den % $num)) //test if divisible
|| ($this->gcd(abs($num),abs($den)) != 1); //gcd
}
function getNumerator() {
return $this->_numerator;
}
function getDenominator() {
return $this->_denominator;
}
function setNumerator($int) {
$this->_numerator = (int) $int;
}
function setDenominator($int) {
if ($int == 0) {
trigger_error('Denominator cannot be zero', E_USER_WARNING);
return;
}
$this->_denominator = (int) $int;
}
function &getReciprocal() {
if ($this->getNumerator() == 0) {
trigger_error('Zero has no reciprocal', E_USER_NOTICE);
return false;
}
return new Fraction($this->getDenominator(), $this->getNumerator());
}
function &getNegative() {
return new Fraction(-($this->getNumerator()), $this->getDenominator());
}
function toPrimitive() {
return $this->getNumerator() / $this->getDenominator();
}
function toString() {
return $this->getNumerator() . '/' . $this->getDenominator();
}
function gcd($a, $b) {
return Fraction::_euclidianAlgorithm($a,$b);
}
function _euclidianAlgorithm($a, $b) {
while ($b != 0) {
$t = $b;
$b = $a % $b;
$a = $t;
}
return $a;
}
//not working...
function _binaryAlgorithm($u, $v) {
$k = 0;
if ($u == 0)
return $v;
if ($v == 0)
return $u;
while (($u & 1) == 0 && ($v & 1) == 0) { // while both u and v are even
$u >> 1; // shift u right, dividing it by 2
$v >> 1; // shift v right, dividing it by 2
$k++; // add a power of 2 to the final result
}
// At this point either u or v (or both) is odd
do {
if (($u & 1) == 0) //if u is even
$u >> 1; //divide u by 2
elseif (($v & 1) == 0) //else if v is even
$v >> 1; //divide v by 2 */
elseif ($u >= $v) //u and v are both odd
$u = ($u-$v) >> 1;
else //u and v both odd, v > u
$v = ($v-$u) >> 1;
} while ($u > 0);
return $v << $k; //returns v * 2^k
}
}
?>Code: Select all
<?php
include_once(dirname(__FILE__) . '/Fraction.php');
include_once('simpletest/unit_tester.php');
class SimpleTest_Fraction extends UnitTestCase{
function test_Fraction() {
$fraction =& new Fraction(1,2);
$this->assertEqual($fraction->getNumerator(), 1);
$this->assertEqual($fraction->getDenominator(), 2);
$fraction =& new Fraction(-1, -2);
$this->assertEqual($fraction->getNumerator(), -1);
$this->assertEqual($fraction->getDenominator(), -2);
$fraction =& new Fraction(0, 0);
$this->assertError('Denominator cannot be zero');
}
function test_isReducible() {
$fraction =& new Fraction(2,4);
$this->assertTrue($fraction->isReducible());
$fraction =& new Fraction(-2,-4);
$this->assertTrue($fraction->isReducible());
$fraction =& new Fraction(-1,-3);
$this->assertTrue($fraction->isReducible());
$fraction =& new Fraction(6,10);
$this->assertTrue($fraction->isReducible());
$fraction =& new Fraction(29,13);
$this->assertFalse($fraction->isReducible());
$fraction =& new Fraction(-29,13);
$this->assertFalse($fraction->isReducible());
$fraction =& new Fraction(0,13);
$this->asserttrue($fraction->isReducible());
$fraction =& new Fraction(3,-1);
$this->asserttrue($fraction->isReducible());
}
function test_reduce() {
$fraction =& new Fraction(2,4);
$fraction->reduce();
$this->assertEqual($fraction, new Fraction(1,2));
$fraction =& new Fraction(-2,-4);
$fraction->reduce();
$this->assertEqual($fraction, new Fraction(1,2));
$fraction =& new Fraction(-1,-3);
$fraction->reduce();
$this->assertEqual($fraction, new Fraction(1,3));
$fraction =& new Fraction(29,13);
$fraction->reduce();
$this->assertEqual($fraction, new Fraction(29,13));
$fraction =& new Fraction(0,13);
$fraction->reduce();
$this->assertEqual($fraction, new Fraction(0,1));
$fraction =& new Fraction(3,1);
$fraction->reduce();
$this->assertEqual($fraction, new Fraction(3,1));
$fraction =& new Fraction(3,-1);
$fraction->reduce();
$this->assertEqual($fraction, new Fraction(-3,1));
}
function test_gcd() {
$this->assertEqual(Fraction::gcd(10,5), 5);
$this->assertEqual(Fraction::gcd(3,5), 1);
$this->assertEqual(Fraction::gcd(27,6), 3);
}
function test_getNegative() {
$frac =& new Fraction(1,2);
$this->assertEqual($frac->getNegative(),new Fraction(-1,2));
}
function test_getReciprocal() {
$frac =& new Fraction(1,2);
$this->assertEqual($frac->getReciprocal(),new Fraction(2,1));
}
function test_add() {
$frac1 =& new Fraction(1, 2);
$frac2 =& new Fraction(3, ;
$this->assertEqual($frac1->add($frac2), new Fraction(7, );
$frac1 =& new Fraction(24, 36);
$frac2 =& new Fraction(1, 3);
$this->assertEqual($frac1->add($frac2), new Fraction(1, 1));
}
function test_subtract() {
$frac1 =& new Fraction(1, 2);
$frac2 =& new Fraction(3, ;
$this->assertEqual($frac1->subtract($frac2), new Fraction(1, );
$frac1 =& new Fraction(24, 36);
$frac2 =& new Fraction(1, 3);
$this->assertEqual($frac1->subtract($frac2), new Fraction(1, 3));
}
function test_multiply() {
$frac1 =& new Fraction(1, 2);
$frac2 =& new Fraction(3, ;
$this->assertEqual($frac1->multiply($frac2), new Fraction(3, 16));
$frac1 =& new Fraction(24, 36);
$frac2 =& new Fraction(1, 3);
$this->assertEqual($frac1->multiply($frac2), new Fraction(2, 9));
}
function test_divide() {
$frac1 =& new Fraction(1, 2);
$frac2 =& new Fraction(3, ;
$this->assertEqual($frac1->divide($frac2), new Fraction(4, 3));
$frac1 =& new Fraction(3, 4);
$frac2 =& new Fraction(3, 1);
$this->assertEqual($frac1->divide($frac2), new Fraction(1, 4));
}
function test_toPrimitive() {
$fraction = new Fraction(1,2);
$this->assertEqual($fraction->toPrimitive(), 0.5);
$fraction = new Fraction(1,3);
$this->assertEqual($fraction->toPrimitive(), 1 / 3);
$fraction = new Fraction(1,10);
$this->assertEqual($fraction->toPrimitive(), 0.1);
$fraction = new Fraction(2,1);
$this->assertIdentical($fraction->toPrimitive(), 2);
}
function test_toString() {
$fraction = new Fraction(1,2);
$this->assertEqual($fraction->toString(), '1/2');
}
}
?>