1

I really badly need a php function that will convert a millimeter into a fraction (in inches).

For example:

16mm = 5/8 of an inch
321mm = 12 41⁄64 inches

I have searched high and low for any php example and I am completely stumped. Is there any kind soul out there that has something like this built.

Thanks so much for your help!

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
LargeTuna
  • 2,694
  • 7
  • 46
  • 92
  • lol what? this makes no sense. – shapeshifter Dec 10 '12 at 23:33
  • How does 16mm = 5/8 321mm..? – aug Dec 10 '12 at 23:34
  • You should go see the site [here](http://www2.whidbey.net/ohmsmath/webwork/javascript/decin2fr.html). It's javascript, but should work. – jaudette Dec 10 '12 at 23:34
  • I can't understand how you want to do the conversion or what it's converting to. There are ways to convert decimal numbers to fractions, yes, but you have to tell us how you want to do the conversion. What are the conversion scales? – Sherif Dec 10 '12 at 23:35
  • Forgot to change the title of my post before submitting. In any case, if you take a look at this page: http://www.metric-conversions.org/length/millimeters-to-inches.htm ... and put in 16 in the box, you will see it returns 5/8. If you enter 321 it will return 12 41⁄64. I need a php function that can do the same thing as that. – LargeTuna Dec 10 '12 at 23:35
  • So you want to convert millimeters to inches? – shapeshifter Dec 10 '12 at 23:37
  • GoogleGuy, the scale needs to be to the 32th's. – LargeTuna Dec 10 '12 at 23:37
  • shapeshifter, yes that is correct. (inches as a fraction) – LargeTuna Dec 10 '12 at 23:38
  • fractions and inches, this is the 21st century you know. –  Dec 10 '12 at 23:39

2 Answers2

1

The easy part is converting from millimeters to inches – just divide by 25.4. The hard part is finding the nearest 32nd (or 16th, 64th, etc.).

At the end of this answer, I include a function for doing so called toMixedNumber(). It follows the following algorithm:

  • Multiply the floating-point value by the desired denominator, rounding to the nearest unit.
  • Divide by the denominator. The quotient is the integer part, and the remainder is the numerator.
  • Optionally, reduce the fractional part to lowest terms by dividing both the numerator and the denominator by the greatest common divisor (GCD). The GCD can be calculated using Euclid's algorithm.
  • Format the integer and fractional parts as a string in "i", "n/d", or "i n/d" format as appropriate. In the "i n/d" case, remove any minus sign in the fractional part.

Using the function is straightforward:

const MM_PER_IN = 25.4;
echo toMixedNumber(14 / MM_PER_IN, 32) . "\n"; // 9/16
echo toMixedNumber(55 / MM_PER_IN, 32) . "\n"; // 2 5/32
echo toMixedNumber(321 / MM_PER_IN, 32) . "\n"; // 12 5/8
echo toMixedNumber(321 / MM_PER_IN, 64) . "\n"; // 12 41/64

Interestingly, if the denominator is always a power of two (as in your case), an optimization becomes possible. For a proper dyadic fraction with a positive numerator, the value of the least significant "1" bit in the numerator is the GCD of the numerator and denominator:

if ($reduce) {
    $gcd = $num & -$num;
    $num /= $gcd;
    $denom /= $gcd;
}

I adapted the bit twiddling trick from Innovative way for checking if number has only one on bit in signed int, and on my computer, it speeds up the function by about 20%. (It works because the value of any bit is a divisor of all values of more significant bits, and the denominator's sole "1" bit is more significant than any in the numerator.) However, I chose not to include it.


function toMixedNumber($arg, $denom, $reduce = true) {
    $num = round($arg * $denom);
    $int = (int)($num / $denom);
    $num %= $denom;

    if (!$num) {
        return "$int";
    }

    if ($reduce) {
        // Use Euclid's algorithm to find the GCD.
        $a = $num < 0 ? -$num : $num;
        $b = $denom;
        while ($b) {
            $t = $b;
            $b = $a % $t;
            $a = $t;
        }

        $num /= $a;
        $denom /= $a;
    }

    if ($int) {
        // Suppress minus sign in numerator; keep it only in the integer part.
        if ($num < 0) {
            $num *= -1; 
        }
        return "$int $num/$denom";
    }

    return "$num/$denom";
}

License for the above example code

Community
  • 1
  • 1
PleaseStand
  • 31,641
  • 6
  • 68
  • 95
0

Basic answer, based on this site.

function toFraction($inches)
{
  $frac = $inches - intval($inches);
  return intval($frac * 32);
}

The function returns the 32nd of an inch.

You can have the number of inches with intval.

For mm to inches conversion, just multiply by 0.0393700787

function toInches($mm)
{
  $inches = $mm * 0.0393700787;
  $wholeInches = intval($inches);
  $fraction = toFraction($inches);
  return array('inches' => $wholeInches, '32nds' => $fraction);
}

I leave the simplification of 32nds to you...

jaudette
  • 2,305
  • 1
  • 20
  • 20