php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #74925 Mismatching floating values
Submitted: 2017-07-14 14:42 UTC Modified: 2017-07-17 16:47 UTC
Votes:1
Avg. Score:1.0 ± 0.0
Reproduced:0 of 1 (0.0%)
From: tuepp at gmx dot de Assigned:
Status: Not a bug Package: PHP Language Specification
PHP Version: 7.0.21 OS: Windows
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: tuepp at gmx dot de
New email:
PHP Version: OS:

 

 [2017-07-14 14:42 UTC] tuepp at gmx dot de
Description:
------------
Floating number comparison fails for numbers that have to be rounded internal.
This bug may be over 10 years old. I've reported it 5 years ago and it is still not fixed. Now I have an example with one instead of 3 lines of code what might be more shoking. I've documented this bug in my final exam 6 years ago and it feeled like I got some extra points for it - so thank you. But now it's really time to fix it! I'm not sure if I'll report it a third time in another 5 years... So go, get it!

Test script:
---------------
<?php
echo (54.83 + 0.01 == 54.84) ? 'ok' : 'fail'; //fail
echo "<br>\n";
echo ((3 * 202.3) == 606.9) ? 'ok' : 'fail'; //fail
echo "<br>\n";
for($v = -1; $v < 0; $v += 0.2){
	echo "$v; "; // -1; -0.8; -0.6; -0.4; -0.2; -5.5511151231258E-17;
}

Expected result:
----------------
ok
ok
-1; -0.8; -0.6; -0.4; -0.2 

Actual result:
--------------
fail
fail
-1; -0.8; -0.6; -0.4; -0.2; -5.5511151231258E-17;

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2017-07-14 14:49 UTC] krakjoe@php.net
-Status: Open +Status: Not a bug
 [2017-07-14 14:49 UTC] krakjoe@php.net
Floating point values have a limited precision. Hence a value might 
not have the same string representation after any processing. That also
includes writing a floating point value in your script and directly 
printing it without any mathematical operations.

If you would like to know more about "floats" and what IEEE
754 is, read this:
http://www.floating-point-gui.de/

Thank you for your interest in PHP.


 [2017-07-17 16:41 UTC] tuepp at gmx dot de
I know about this issue - and I wonder why there shouldn't be some internal rounding-mechanism.

"Thank you for your interest in PHP." - that must be a bad joke...
 [2017-07-17 16:47 UTC] rasmus@php.net
Round to what? For display purposes you can set a precision, but arbitrarily doing internal rounding would lead to chaos. I don't know of any programming language that does that. Pick any language and try your example and you will get similar results. This is how computers handle floating point natively. It is up to the programmer to apply whatever rounding is appropriate for their situation.
 [2017-07-18 18:28 UTC] neclimdul at gmail dot com
I thought was weird for a sec looking at the output of php's values but was then reminded that's just the display misrepesenting the internal value. As Rasmus stated the values are consistent with other languages.

https://gist.github.com/neclimdul/79d887d655ee5cec4bec50faa94c4382

What seems to be different in Ruby and Node is that they auto expand out the value and show the float weirdness when you just print the value. C doesn't and PHP is more in line with its behavior.

Basically, try this for your test script.
---------------
<?php
var_dump(54.83 + 0.01);
printf("%.18e\n", 54.83 + 0.01);
var_dump(54.83 + 0.01 == 54.84);
var_dump(3 * 202.3);
printf("%.18e\n", (3 * 202.3));
var_dump((3 * 202.3) == 606.9);
for($v = -1; $v < 0; $v += 0.2){
  printf("%.18e\n", $v);
  var_dump($v);
}
Results
---------------
float(54.84)
5.483999999999999631e+1
bool(false)
float(606.9)
6.069000000000000909e+2
bool(false)
-1.000000000000000000e+0
int(-1)
-8.000000000000000444e-1
float(-0.8)
-6.000000000000000888e-1
float(-0.6)
-4.000000000000000777e-1
float(-0.4)
-2.000000000000000666e-1
float(-0.2)
-5.551115123125782702e-17
float(-5.5511151231258E-17)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Wed Nov 06 14:01:28 2024 UTC