Converting a Decimal to a Fraction in PHP
· 289 wordsBelow is a helper function to convert a decimal, like for instance 6.5, into a fraction, 13/3 in this example. In fact the function will return an array with the number on the top of the fraction (the numerator) being the first item and the number at the bottom (the denominator) being the second item.
Edit 25th Nov 2016: Changed the function to be more accurate and added some phpunit tests for it.
The Function:
/**
* Convert a decimal (e.g. 3.5) to a fraction (e.g. 7/2).
* Adapted from: http://jonisalonen.com/2012/converting-decimal-numbers-to-ratios/
*
* @param float $decimal the decimal number.
*
* @return array|bool a 1/2 would be [1, 2] array (this can be imploded with '/' to form a string)
*/
function decimalToFraction($decimal)
{
if ($decimal < 0 || !is_numeric($decimal)) {
// Negative digits need to be passed in as positive numbers
// and prefixed as negative once the response is imploded.
return false;
}
if ($decimal == 0) {
return [0, 0];
}
$tolerance = 1.e-4;
$numerator = 1;
$h2 = 0;
$denominator = 0;
$k2 = 1;
$b = 1 / $decimal;
do {
$b = 1 / $b;
$a = floor($b);
$aux = $numerator;
$numerator = $a * $numerator + $h2;
$h2 = $aux;
$aux = $denominator;
$denominator = $a * $denominator + $k2;
$k2 = $aux;
$b = $b - $a;
} while (abs($decimal - $numerator / $denominator) > $decimal * $tolerance);
return [
$numerator,
$denominator
];
}
Some Tests for it:
public function test_decimal_to_fraction_conversion()
{
$this->assertEquals([0, 0], decimalToFraction(0));
$this->assertEquals([1, 4], decimalToFraction(0.25));
$this->assertEquals([1, 3], decimalToFraction(0.3333333333333));
$this->assertEquals([1, 2], decimalToFraction(0.5));
$this->assertEquals([1, 1], decimalToFraction(1));
$this->assertEquals([6, 5], decimalToFraction(1.2));
$this->assertEquals([1329, 997], decimalToFraction(1.333));
$this->assertEquals([4, 3], decimalToFraction(1.3333));
$this->assertEquals([3, 2], decimalToFraction(1.5));
$this->assertEquals([2, 1], decimalToFraction(2));
$this->assertEquals([7, 2], decimalToFraction(3.5));
$this->assertEquals([PHP_INT_MAX, 1], decimalToFraction(PHP_INT_MAX));
$this->assertFalse(decimalToFraction(-1));
$this->assertFalse(decimalToFraction("string"));
}
∞