1

So while programming using PHP we discovered something odd was happening.

We pulled our numbers from the database and had our results set like normal.

Then we do to evaluate the results in the if statement and if when like such

if(abs($number1 + $number2) < .05){
    // do that
}else{
    // do that
}

When we printed the output from the abs($number1 + $number2) it showed a result of .05, so logically the else part our if statement should have executed but it evaluated .05 < .05 as true. Why?

Mark Hill
  • 1,769
  • 2
  • 18
  • 33
  • When the underlying representations of the base 2 digits that get rendered as decimal .05 are not the same. – Álvaro González Oct 28 '15 at 17:32
  • Please have a look in this http://stackoverflow.com/questions/3148937/compare-floats-in-php – Chin Lee Oct 28 '15 at 17:34
  • This article may also be useful: http://php.net/manual/en/language.types.float.php which also has some tips on comparing floats – Octopus Oct 28 '15 at 17:34
  • Floating point numbers are not precise. Use bcmath library: http://php.net/manual/en/book.bc.php. bccomp is your function. – user4035 Oct 28 '15 at 17:39

2 Answers2

3

Because a float value is always not exactly precise. So 0.05 could internally very well be 0.0499999999 which is smaller than 0.05.

Using a very small epsilon value that you allow as error would solve your problem.

Niki van Stein
  • 10,564
  • 3
  • 29
  • 62
  • so then how is this issue corrected to make it so that they are evaluated correctly? – Mark Hill Oct 28 '15 at 17:33
  • A hackfix is write < 0.0500001 – Niki van Stein Oct 28 '15 at 17:34
  • 3
    @Mark: You typically have a small delta where you allow the value to be in. I.e. `targetValue - delta < testvalue < targetvalue + delta`. At least this is done in unit tests. It obviously depends on the precision you require. – Felix Kling Oct 28 '15 at 17:36
1

Your results are not really that odd. When working with floats you need to account for the concept of "precision".

This article from the PHP docs says:

"So never trust floating number results to the last digit, and do not compare floating point numbers directly for equality. If higher precision is necessary, the arbitrary precision math functions and gmp functions are available."

The article offers some example code of how one might compare floating values:

$a = 1.23456789;
$b = 1.23456780;
$epsilon = 0.00001;

if(abs($a-$b) < $epsilon) {
        echo "true";
}
Octopus
  • 8,075
  • 5
  • 46
  • 66