Compare Floats in PHP

Compare floats in php

If you do it like this they should be the same. But note that a characteristic of floating-point values is that calculations which seem to result in the same value do not need to actually be identical. So if $a is a literal .17 and $b arrives there through a calculation it can well be that they are different, albeit both display the same value.

Usually you never compare floating-point values for equality like this, you need to use a smallest acceptable difference:

if (abs(($a-$b)/$b) < 0.00001) {
echo "same";
}

Something like that.

PHP float comparison

you can just do it this way:

//just a check if it is float, than round it to 1 decimal number and compare

if(is_float($a)){
echo 'not a float';
$a = round($a,1);
}

and output will be 'IF'

Is there any way to compare float numbers correctly in PHP?

Use this method:

$a = 0.2;
if ( abs($a - 0.2) < 0.00001 )
return true;
else
return false;

Comparing floats - same number, but does not equal?

floating point numbers have limited precision. view the warning about comparing them here:

http://php.net/manual/en/language.types.float.php

PHP Comparing float values

I found where the problem actually was. My getBalance() method was actually returning the value 1 when being converted to a float. 1 was the position of the record in the array. Changing the declaration of $floatCurrentBalance to: $floatCurrentBalance = floatval($currentBalance['balance']);

Formulas for comparing float equality in PHP

This probably allows checking epsilon with a relative error rather than an absolute error.

Compare these two cases:

function areEqual(float $a, float $b) : bool {
return abs(($a - $b) / $b) < 0.00001;
}
areEqual(10000, 10000.01);
areEqual(0.0000001, 0);

Fact about the example values above: Our epsilon here is 0.00001 for convenience ‐ the smallest epsilon possible is much smaller than these values anyway, so let's ignore this fact. Our algorithm assumes that $a and $b are both similar, so it does not matter whether we divide by $a or $b. Actually, 10000 should be much larger than that (a very enormous exponent), and 0.0000001 can be much smaller, but for the sake of convenience, let's assume these are the values that may cause problems.

Now you can already see the difference.

For the large numbers: If the compared floats are extremely large, epsilon may be too small. The float internally can only store a definite number of digits for precision, while the exponent can be way greater than that. As a result, the source of floating point error, i.e. the final digits of floats, would appear at somewhere that can be higher than the unit digits. In other words, for extremely large floats, the absolute error can be greater than 1, much less our epsilon of 0.00001.

For the small numbers: This is even more obvious. Both numbers are smaller than the epsilon already. Even if you compare them with 0, while the relative error is infinitely large, you still think that they are equal. For this case, you either multiply up both operands, or you decrease the epsilon. They are actually the same, but in terms of implementation, it is more convenient to divide the difference with one of the operands, which will multiply up for small numbers (/ 0.0001 is equivalent to * 10000) or divide down for large numbers (/ 10000 while the difference is hopefully way smaller than 10000)

There is another name for this check. While abs($a - $b) is called the absolute error, we usually use the relative error, which is absolute error ÷ approximate value. Since the values can be negative as well, we abs the whole thing ($a - $b) / $b instead. Our "epsilon", 0.00001, in this case, means that our tolerate relative error is 0.00001, i.e. 0.001% error.


Keep in mind that this is still not absolutely safe. After numerous transformations in your program, you may, for example, add/multiply your numbers with some big numbers, then subtract down again, leaving the impure error in the big numbers somewhere still negligible to humans but notable to your epsilon value. Therefore, always think twice before choosing an epsilon value or float comparison algorithm.

As the best practice, avoid adding, subtracting or multiplying big numbers with small numbers. They will increase the chance of errors. When developing (especially simplifying) your algorithms, always put into consideration that their might be an error in your floats. This may increase work load to a stupid extent, but as long as you are aware of it, this kind of worry sometimes saves you from getting kicked out of teams.

Sample Image

php integer and float comparison mismatch

Notice the big red warning in the PHP Manual!

Never expect anything when comparing floats. The result of round, even if the precision is 0, is still a float. In your particular case it happened that the result was a little bigger than expected, so casting to int resulted in equality, but for other numbers it might as well happen for it to be a little smaller than expected and casting to int won't round it, but truncate it, so you can't use casting as a workaround. (As a note, a better solution than yours would be casting to string :), but still a lousy option.)

If you need to work with amounts of money always use the BC Math extension.

For rounding with BC Math you can use this technique:

$x = '211.9452';
$x = bcadd($x, '0.005', 2);

Good luck,

Alin



Related Topics



Leave a reply



Submit