1

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
Miguel Vieira
  • 144
  • 3
  • 17

2 Answers2

1

By default the bc-functions round to 0 decimals. You can change this behavior by either using bcscale or by by changing the bcmath.scale value in your php.ini.

PtrTon
  • 3,705
  • 2
  • 14
  • 24
0

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));
}
Miguel Vieira
  • 144
  • 3
  • 17