Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

issue in double value comparison with php

I try to create unit test cases to check my table values are correct or wrong.

This is my codes

echo $a = 2/9;
echo "<br>".$b=0.22222222222222;

echo "<br>".gettype($a);
echo "<br>".gettype($b);
if($a==$b){
    echo "<br>". "equal";
}else echo "<br>". "Not equal";


if((string)$a==(string)$b){
    echo "<br>". "equal";
}else echo "<br>". "Not equal";

Why my first if condition not working? I can't find the reason. Please help me.

like image 445
DEVOPS Avatar asked Mar 26 '12 05:03

DEVOPS


People also ask

Why would you use === instead of == in PHP?

== Operator: This operator is used to check the given values are equal or not. If yes, it returns true, otherwise it returns false. === Operator: This operator is used to check the given values and its data type are equal or not. If yes, then it returns true, otherwise it returns false.

Can you use == to compare doubles?

Using the == Operator As a result, we can't have an exact representation of most double values in our computers. They must be rounded to be saved. In that case, comparing both values with the == operator would produce a wrong result. For this reason, we must use a more complex comparison algorithm.

How does precision compare to double?

To compare two floating point or double values, we have to consider the precision in to the comparison. For example, if two numbers are 3.1428 and 3.1415, then they are same up to the precision 0.01, but after that, like 0.001 they are not same.

What is double in PHP?

PHP supports the following data types: String. Integer. Float (floating point numbers - also called double)


1 Answers

The test violates a cardinal rule of floating point programming: never do equality comparisons.

There are a number of problems that stem from the fact that floating point fractions have a large yet finite number of bits. These problems are commonly called "rounding errors" although for the most part they are not errors but format limitations.

For example, because of the way we write numbers when programming ... as decimal strings ... most of the numbers we can write do not have a corresponding representation in the floating point format if they have a decimal fraction. The fractional part repeats in base two.

This largely rules out comparing floating point numbers exactly, except, ironically, between integral values. You need to implement a fuzzy comparison such as abs(a - b) < epsilon.

And actually, your 2/9 is a jackpot case that doesn't have a finite representation as either a decimal string or a binary string!1

To compare 2/9 successfully for equality with a constant places more requirements for perfection on the program, the interpreter, and library than can be counted on.

For example, you would have to type more 2s than you need and the interpreter would have to round the constant's low order bits with knowledge of more precision than the format has. The machine actually has a few bits of extra knowledge when performing the operation but the interpreter may not when converting the constant. Also, the runtime rounding is subject to various options and a language like PHP may not even specify exactly how unrepresentable constants are rounded from source code to internal form.

And actually it's worse than that, because the individual 0.2 / 10n components in the decimal string also do not have exact binary equivalents. So, it's quite likely that a really perfect and faithful conversion of 0.22222222222222 does not actually equal a best-effort representation of the actual 2/9. You cannot express as a finite decimal string the exact base-2 fraction that most closely represents 2/9 in any specific (finite) number of bits.

(We must have somewhere a standard answer about not doing equality comparisons with floating point numbers.)


1. Every machine fraction is a rational number of the form x/2n. Now, the constants are decimal and every decimal constant is a rational number of the form x/(2n * 5m). The 5m numbers are odd, so there isn't a 2n factor for any of them. Only when m == 0 is there a finite representation in both the binary and decimal expansion of the fraction. For example, 1.25 is exact because it's 5/(22*50) but 0.1 is not because it's 1/(20*51). And for the rational number 2/9, there is neither a 2nor a 5m factor.

like image 50
DigitalRoss Avatar answered Oct 17 '22 12:10

DigitalRoss