Why cannot compare double values directly for equality?

  Peter        2012-06-27 09:01:36       10,515        0    

A question in PHP: Get some value from the database and use floatval() to convert it to floatint point value, then compare it with another value which is also converted to floating point value with floatval(). These two values are the same when using var_dump() to output, the two outputs are float(8.87), they are the same. But when comparing them for equality, the result is weird., they are not equal. Why?

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/

PHP  FLOATING  PRECISION  COMPARE  EQUALITY 

       

  RELATED


  0 COMMENT


No comment for this article.



  RANDOM FUN

Pair programming