Skip to content

Instantly share code, notes, and snippets.

@JeffreyHyer
Created August 31, 2016 23:27
Show Gist options
  • Save JeffreyHyer/5c8bf46ecdf82f068ace3a493acc2c4f to your computer and use it in GitHub Desktop.
Save JeffreyHyer/5c8bf46ecdf82f068ace3a493acc2c4f to your computer and use it in GitHub Desktop.
<?php
/**
* Generate a human-friendly fraction approximation given a nasty-looking
* number with lots of digits after the decimal point.
*
* @param double $number The number for which to calculate the nearest friendly fraction
* @param boolean $string Return the human-readable string of the fraction (default)
* or return an array of the fractions parts (whole number, numerator,
* and denominator)
*
* @return string|array Returns a string containing the human-readable representation of the
* friendly fraction (e.g. 4-5/16) or an array of the fractions parts
* that includes the friendly string as well in the "human" key.
* (e.g. ["whole" => 4, "numerator" => 5, "denominator" => 16, "human" => "4-5/16"])
*/
function friendlyFraction($number, $string = true) {
$allowedDen = array(2, 4, 8, 16);
$whole = ($number - fmod($number, 1));
$fraction = fmod($number, 1);
$num = 0;
$den = 1;
$closest = 1;
foreach ($allowedDen as $attempt) {
for ($i = 1; $i < $attempt; $i++) {
$val = ($i / $attempt);
if ($val == $fraction) {
$num = $i;
$den = $attempt;
$closest = $val;
break 2;
}
else if (abs($val - $fraction) < abs($closest - $fraction)) {
$closest = $val;
$num = $i;
$den = $attempt;
}
}
}
$human = (($whole > 0) ? "{$whole}-{$num}/{$den}" : "{$num}/{$den}");
return (($string) ? $human : array("whole" => $whole, "numerator" => $num, "denominator" => $den, "human" => $human));
}
Print "<pre>";
print_r(friendlyFraction(0.286));
Print "</pre>";
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment