phpfloating-pointbcmath

How to multiply small floats with unkown number of decimal places in PHP withouth getting zero because of scientific notation?


I'm trying to multiply some small numbers in PHP, but bcmul is returning zero because the float value is being turned into scientific notation.

I tried using sprintf('%.32f',$value) on the small float values, but since the number of decimal places is unknown, it gets the wrong rounding, and then it'll cause rounding errors when multiplying.

Also, I can't use strpos('e',$value) to find out if it's scientific notation number, because it doesn't finds it even if I cast it as a string with (string)$value

Here's some example code:

  $value = (float)'7.4e-5'; // This number comes from an API like this

  $value2 = (float)3.65; // Another number from API

  echo bcmul($value,$value2); // 0

Solution

  • Okay, I found a way to solve it, so, here's how to multiply very small floating point numbers without needing to set an explicit scale for the numbers:

    function getDecimalPlaces($value) {
    // first we get how many decimal places the small number has
    // this code was gotten on another StackOverflow answer
    
       $current = $value - floor($value);
       for ($decimals = 0; ceil($current); $decimals++) {
          $current = ($value * pow(10, $decimals + 1)) - floor($value * pow(10, $decimals + 1));
       }
       return $decimals;
    } 
    
    function multiplySmallNumbers($value, $smallvalue) {
        
       $decimals = getDecimalPlaces($smallvalue); // Then we get number of decimals on it
       $smallvalue = sprintf('%.'.$decimals.'f',$smallvalue ); // Since bcmul uses the float values as strings, we get the number as a string with the correct number of zeroes
       return (bcmul($value,$smallvalue));
    }