To analyze this question, we need to start with PHP data types. PHP uses weak types. In PHP, floating point values are stored using C's double precision type, so we need to understand how double precision values are stored in memory in C. Floating-point value storage is represented conforming to the IEEE 754 standard (V = (-1)s x M x 2e ).
- sign : s determines the negativeness or positiveness of the number
- significant : M represents the precision bits of the number
- exponent : e is the exponential
The bits to represent a floating-point number are divided into 3 sections.
- 1 bit for the s
- k bits for the e
- n bits for the M
For double precision value in C, s, e and M are 1 bit, 11 bits and 52 bits respectively, in total it's 64 bits( 8 bytes).
After we know how double precision values are stored in memory, we need to check how M is to store the fraction with binary bits.
For a decimal number d, it can be expressed as
while a decimal number b expressed in binary is:
Assume we just consider limited length coding (32 bits or 64 bits), then in decimal format, we cannot accurately represent 1/3 or 3/5. Similarly, only those can be written as x*2y format can be expressed accurately in binary format. Other values can only be represented approximately.
Since double values can only be stored approximately, it's unsafe to directly compare two double values for equality.
For example.
<?php
$a = 2.2;
$d = 0.3 + 1.9;
var_dump($a);
var_dump($d);
//Wrong, double values cannot be compared directly
var_dump($a == $d);
//The proper way to compare two double values
//0.000001 is a threshold value
var_dump(abs($a - $d) < 0.000001);
?>
The output
float(2.2)
float(2.2)
bool(false)
bool(true)
For other languages, the same problem for representing floating-point number exists. So never trust floating numbers, do not compare floating point numbers directly for equality.
Reference : http://sunkid.me/blog/2012/06/26/why-can-not-compare-the-double/