I have an associative array whose values are floats, which are supposed to be probabilities. As such, I sum them up and require that the result is in fact 1.
$total = array_sum($array);
echo '$total = '.$total."\n";
if ($total == 1) {
die("total is 1");
} else {
die("total is not 1");
}
This mysteriously outputs:
$total = 1
total is not 1
Doing a var_dump($total)
yields float(1)
, and yet even $total == (float)1
returns false.
What's going on?
Floating point values are by nature imprecise and are very rarely equal to one another due to the way they are stored and rounding errors. You should be comparing floats by seeing if the two values are "close enough". That is, comparing the absolute value of the difference between the two values to a significantly small margin of error (often referred to as "epsilon").
One such implementation may be:
if (abs($total - 1) < 0.000000001)
die("total is 1");
} else {
die("total is not 1");
}
Note that only your application's requirements can truly determine what a safe margin of error is and at what point numbers should be rounded for display.
If you are dealing with currency values, for example, and require exact precision, a better solution would be to forgo floating-point arithmetic entirely. One option in this case would be to use an integer type and store the number as cents, dividing only at the last minute to display the number to the user (or not even dividing, and injecting a decimal point into the string instead).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With