php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #78294 Unexpected lose equality result
Submitted: 2019-07-15 12:45 UTC Modified: 2019-07-15 12:54 UTC
From: iuli dot butuc at yahoo dot com Assigned:
Status: Not a bug Package: *Math Functions
PHP Version: Irrelevant OS: Windows 10
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: iuli dot butuc at yahoo dot com
New email:
PHP Version: OS:

 

 [2019-07-15 12:45 UTC] iuli dot butuc at yahoo dot com
Description:
------------
Tested on php versions >= 5.6.
The lose equality result for '201905025815311.33' == '201905025815311.34' is true for some reason i cannot identify. Needless to say using using the === operator fixes the issue.

But the result for me is strange. Those strings are probably stored as floats in memory because they have a perfect valid float format. But the float comparison for 201905025815311.33 == 201905025815311.34 fails as well(evaluates to true).

Even if the numbers are rounded, it does not explain how can give the right result for 201905025815311.33 == 201905025815311.32 which should have the same "rounding" rules as 201905025815311.33 == 201905025815311.34. Maybe the 1.33 ending is the problem, but does not ring a bell to me from a mathematical perspective.

Dumping the PHP_FLOAT_MAX constant on php versions that have it (7.2+) suggest that php should not have any trouble working with these numbers.

Test script:
---------------
var_dump('201905025815311.33' == '201905025815311.34');
var_dump('201905025815311.33' == '201905025815311.32');
var_dump(201905025815311.33 == 201905025815311.34);
var_dump(201905025815311.33 == 201905025815311.32);
var_dump(201905025815311.32);
var_dump(201905025815311.33);
var_dump(201905025815311.34);
var_dump(PHP_FLOAT_MAX);

Expected result:
----------------
bool(false)
bool(false)
bool(false)
bool(false)
float(2.0190502581531E+14)
float(2.0190502581531E+14)
float(2.0190502581531E+14)
float(1.7976931348623E+308)

Actual result:
--------------
bool(true)
bool(false)
bool(true)
bool(false)
float(2.0190502581531E+14)
float(2.0190502581531E+14)
float(2.0190502581531E+14)
float(1.7976931348623E+308)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-07-15 12:54 UTC] daverandom@php.net
-Status: Open +Status: Not a bug
 [2019-07-15 12:54 UTC] daverandom@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

This is simply due to floating point precision errors, as you have observed.

PHP stores all floats as doubles, and comparisons are done as they would be in C - i.e. $float1 == $float2 in PHP is mapped directly to float1 == float2 in C.

There's nothing that PHP can/will do to change/improve this behaviour.

As a side note, the strings are not actually stored in memory as floats, however valid numeric strings are converted to numbers for comparisons. Whether this is the "correct" behaviour is debatable, however the debate would be purely academic as it isn't likely to change any time soon - it would be a large BC break to do so, and the behaviour is actually useful considering that PHP deals with stringly-typed data a lot (e.g. $_GET, $_POST and friends).
 [2019-07-15 12:59 UTC] danack@php.net
To expand on what Dave said, 201905025815311.33 isn't representable as a floating point number. When you try to create a floating point number with that value, it will be rounded to end either in .32 or .34 depending on various things. 

You can see that for yourself here:
https://babbage.cs.qc.cuny.edu/IEEE-754.old/Decimal.html

"php should not have any trouble working with these numbers."

It has no more trouble than comes naturally with using floating point numbers.
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Mon Jan 25 15:01:23 2021 UTC