Search code examples
phpnumbersnumber-formattingpercentage

How can I simplify a percent (ex. 25%) to a simple statement (ex. 1 out of 4)?


I need to convert an array of numbers and totals into a simple statement.

For example, how can I convert the following, programmatically via PHP, to simple statements like, 1 out of 10, 1 out of 100, and even rounding some (like 2 out of 100 for 9000,400000).

Generate Sample Array:

$arr = array();
for ($i=0; $i < 100; $i++) {
    $n = mt_rand(1,1000);
    $t = mt_rand(10,100000);
    if ($n > $t) continue; // skip!
    $arr[] = array($n,$t);
}
/*
// Generates pairs like:
// Array
// (
//     [0]  => Array ( [0] => 55  [1] => 8774  )
//     [1]  => Array ( [0] => 814 [1] => 11174 )
//     [2]  => Array ( [0] => 255 [1] => 32168 )
//     ...
//     [99] => Array ( [0] => 851 [1] => 24231 )
// )
*/

Run through a function and print simplified results:

foreach ($arr as $a) {
    echo $a[0] . '/' . $a[1] . ' ==> ' . simplifyRatio($a[0],$a[1]) . "\r\n";
}

Can you point me in the right direction on how to accomplish this?

Here's the start of a function I'm working on, but the solution is escaping me.

function simplifyRatio($n,$t) {
    $p = $n/$t;
    if ($p > 0.09) return round($n) . ' out of ' . round($t);
    if ($p > 0.009) return round($n) . ' out of ' . round($t);
}

Ideally the denominator should be: 1,2,3...10,20,30...100,200,300...1000,2000,3000...10000,20000,30000...100000 (max)


Solution

  • I ended up settling for a near match on the pattern 1 out of ___, like so:

    function simplifyRatio($n,$t) {
        $r = $t/$n;
        return '1 out of ' . round($r);
    }
    
    // Examples:
    $arr = array();
    for ($i=0; $i < 100; $i++) {
        $n = mt_rand(1,1000);
        $t = mt_rand(10,100000);
        if ($n > $t) continue; // skip!
        $arr[] = array($n,$t);
    }
    foreach ($arr as $a) {
        echo $a[0] . '/' . $a[1] . ' ==> ' . simplifyRatio($a[0],$a[1]) . "\r\n";
    }
    

    Example Result:

    1000/24819 ==> 1 out of 25
    309/50305 ==> 1 out of 163
    488/99123 ==> 1 out of 203
    322/47610 ==> 1 out of 148
    183/54287 ==> 1 out of 297
    752/67646 ==> 1 out of 90
    240/68854 ==> 1 out of 287
    301/81345 ==> 1 out of 270
    611/16404 ==> 1 out of 27
    522/62992 ==> 1 out of 121
    

    CodePad: http://codepad.org/wu6iOdDq

    Initially I had hoped to end up with rounded denominators (10,20...100,200...1000,2000, etc.), but I'm uncertain how to do this well. I'll happily award an answer that cleans up the denominators of the above.