Answering a Common Question About PHP Floats

Regarding PHP’s floating point numbers, I wrote an article before: What you should know about PHP floats (All ‘bogus’ about the float in PHP) However, I left one thing out at the time, namely the answer to this common question:

1
2
3
4
<?php
    $f = 0.58;
    var_dump(intval($f * 100)); //why does it output 57?
?>


Why is the output 57? Is it a PHP bug? I believe many of you have had this doubt, because plenty of people have asked me questions like this, not to mention how often it comes up on bugs.php.net… To understand the reason, we first need to know how floating point numbers are represented (IEEE 754): taking the 64-bit length (double precision) as an example, a floating point number is represented with 1 sign bit (E), 11 exponent bits (Q) and 52 significand bits (M) (64 bits in total). Sign bit: the highest bit indicates whether the value is positive or negative; 0 means positive and 1 means negative. Exponent bits: they represent the power with base 2 for the value, and the exponent uses an offset representation. Significand: it represents the significant digits after the decimal point of the value. The key point here is how decimals are represented in binary. As for how decimals are represented in binary, you can look it up on Baidu; I won’t repeat it here. What we really need to understand is that, in binary representation, 0.58 is an infinitely long value (the numbers below omit the implicit 1)..

  1. The binary representation of 0.58 is basically (52 bits): 0010100011110101110000101000111101011100001010001111
  2. The binary representation of 0.57 is basically (52 bits): 0010001111010111000010100011110101110000101000111101

And if the binary of these two values is computed using only these 52 bits, they are respectively:

  1. 0.58 -> 0.57999999999999996
  2. 0.57 -> 0.56999999999999995

As for the concrete floating point multiplication of 0.58 100, we won’t go into that much detail; those interested can look at (Floating point). Let’s just look at it roughly, by mental math… 0.58 100 = 57.999999999 and so intval on that naturally gives 57…. So you can see that the key point of this problem is: “a decimal that looks finite to you is infinite in the computer’s binary representation” so, don’t go thinking this is a PHP bug anymore, that’s just how it is….. Article URL: http://www.laruence.com/2013/03/26/2884.html