The test violates the cardinal rule of floating point programming: never conduct equality comparisons.
There are a number of problems associated with the fact that floating point fractions have a large but finite number of bits. These problems are usually called "rounding errors", although for the most part these are not errors, but format restrictions.
For example, due to the way we write numbers when programming ... as decimal strings ... most of the numbers we can write do not have a corresponding representation in floating point format if they have a decimal fraction. The fractional part is repeated in base 2.
This largely eliminates the comparison of floating-point numbers exactly, except, paradoxically, between the integral values. You need to implement a fuzzy comparison, for example abs(a - b) < epsilon.
And in fact, your 2/9
is a jackpot that has no final representation of either a decimal string or a binary string! 1
For comparison, 2/9
successfully for equality with a constant puts more requirements for excellence in the program, interpreter and library than can be considered.
For example, you would need to type more than 2
than you need, and the interpreter would have to combine the bit of the low-order constant bit with knowledge of greater accuracy than the format. The machine actually has a few bits of additional knowledge when performing the operation, but the interpreter cannot do this when converting the constant. In addition, rounding at runtime depends on various parameters, and a language such as PHP may not even indicate exactly how unpredictable constants are rounded from source to internal form.
And in fact, this is worse because the individual 0.2 / 10 n components in the decimal string also do not have exact binary equivalents. Thus, it is likely that a truly perfect and accurate conversion of 0.22222222222222
really is not really equal to the best representation of the actual 2/9
. You cannot express in the form of a final decimal string the exact fraction of base-2, which most accurately represents 2/9 in any particular (final) number of bits.
(We should have somewhere a standard answer about not comparing comparisons with floating point numbers.)
<sub> 1. Each machine fraction is a rational number of the form x / 2 n . Now the constants are decimal, and each decimal constant is a rational number of the form x / (2 n * 5 m ). The number 5 m is odd, so for any of them 2 n does not exist. Only when m == 0 is the final representation in both binary and decimal fractions. For example, 1.25
is accurate because 5 / (2 2 * 5 0 ), but 0.1
not because 1 / (2 0 * 5 1 ). And for a rational number 2/9
there is no factor 2 n or 5 m .