Search code examples
phpalgorithmfinancial

Price in decimals to Price in 32nds


I'm trying to code a function for this : a conversion from Price in decimals to Price in 32nds : Like this calculator : http://www.iotafinance.com/en/Fractional-Decimal-Price-Conversion-Calculator.html

I code a function in PHP but this not working for all the case : Example : For 4.078 decimal, I should have 4.024 in 32nds but i have 4.025

Is there an elegant function ? I think my solution is bad and not working for all the cases.

Thanks a lot

The code in PHP :

<?php

function convert32eme($dec) {
    // Init 
    $pos2 = "";
    $pos3 = "";
    $pre = "";
    $i = 0;
    $aNumberDecimal = explode(".", $dec);
    $iEntier = $aNumberDecimal[0];
    $fDecimal = @$aNumberDecimal[1];

    // Two first décimales in 32eme
    if(isset($fDecimal)) {
        $pos2 = '0.'.(int)$fDecimal;
        while(substr($fDecimal, $i++, 1) == 0) {
            $pre .= "0";
        }
        $pos2 = $pre.$pos2*32; // Multiply 32
        $aNumberDecimal2 = explode(".", $pos2);
        $pos2 = $aNumberDecimal2[0]; // 2 first decimal

        // Third decimales in 8eme of 32eme
        $iEntier2 = $aNumberDecimal2[0];
        $fDecimal2 = @$aNumberDecimal2[1];
        if(isset($fDecimal2)) {
            $c = '0.'.(int)$fDecimal2;
            $pos3 = round($c*8); // Multiply 8
            echo '<br/>Pos3 : '.$pos3;
        }
    }

    // Final
    $fDecimalFinal = ($pos2).($pos3);
    echo '<br/>'.$fDecimalFinal;
    $aFoo = explode('.', round("0.".$fDecimalFinal, 3));
    $fDecimalFinal = @$aFoo[1];
    if(!$fDecimalFinal) {
        $fDecimalFinal = "00";
    }
    return $iEntier.'.'.$fDecimalFinal;
}
function display($dec, $correc, $result) {
    echo '----------------<br/>'.$dec.' - '.$correc;
    if($result == $correc) {
        echo ' <span style="color: green">OK</span>';
    } else
    {
        echo ' <span style="color: red">KO</span>';
    }
    echo '<br/>';
}
function useless($dec, $correc) {
    $result = convert32eme($dec);
    display($dec, $correc, $result);
    return $result;
}

echo '-> ' . useless(100.515625, 100.164).'<br/>'; // OK
echo '-> ' . useless(100.9609375, 100.306).'<br/>'; // OK
echo '-> ' . useless(108.0859, 108.027).'<br/>'; // OK
echo '-> ' . useless(100.03125, 100.01).'<br/>'; // OK
echo '-> ' . useless(100.5, 100.16).'<br/>'; // OK
echo '-> ' . useless(100.00, 100.00).'<br/>'; // OK
echo '-> ' . useless(1000.096, 1000.031).'<br/>'; // OK
echo '-> ' . useless(94949.4564879, 94949.145).'<br/>'; // OK
echo '-> ' . useless(0.454, 0.144).'<br/>'; // OK
echo '-> ' . useless(4.0035, 4.001).'<br/>'; // OK
echo '-> ' . useless(4.0078, 4.002).'<br/>'; // OK
echo '-> ' . useless(4.078, 4.024).'<br/>'; // dont't work
echo '-> ' . useless(4.071, 4.022).'<br/>'; // dont't work

Solution

  • Your conversion function seems very complicated because you have made the bad choice of working on a string instead of working on a number. If you work with numbers, you don't have to worry about the number of zeros after the dot or this kind of things. You only have to calculate and to round the result:

    function convert32($num) {
        $intpart = intval($num);
        return round($intpart + ($num - $intpart)/3.125, 3);
    }
    

    with the 8th part:

    function convert32($num) {
        $intpart = intval($num);
        $dec32 = ($num - $intpart)*.32;
        $dec8 = ($dec32 - floor($dec32*100)/100)*.8;
        $dec32 = floor($dec32*100)/100;
        return round($intpart + $dec32 + $dec8, 3);
    }
    

    In french trente-deuxième is abbreviated 32e (32e when possible), not 32eme.