简体   繁体   中英

When are two variables considered to be equal?

I've got a few variables stored in an object that (for purposes of troubleshooting) I am extracting and turning into floats for comparison. For some reason some PHP is not considering some of the properties as equal (when they are by all appearances) whether or not I directly compare the properties, extract them, or compare their float value:

$lat1 = $coordinates1->latitude; $lat2 = $coordinates2->latitude;
$lon1 = $coordinates1->longitude; $lon2 = $coordinates2->longitude;
if (floatval($lat1) == floatval($lat2)) {
    $myLog->debug("[".floatval($lat1)."] == [".floatval($lat2)."]");
} else {
    $myLog->debug("[".floatval($lat1)."] != [".floatval($lat2)."]");
}
if (floatval($lon1) == floatval($lon2)) {
    $myLog->debug("[".floatval($lon1)."] == [".floatval($lon2)."]");
} else {
    $myLog->debug("[".floatval($lon1)."] != [".floatval($lon2)."]");
}

The results in the debug log are as follows for two different sets of values:

[42.398264] != [42.442251]
[-83.316297] != [-83.33669]
[42.398264] == [42.398264]
[-83.316297] != [-83.316297]

What am I missing?

The decimal string representations of your floats aren't exactly equal to the floats' true values. It's possible that two floats have different values, but their string representation is the same to some number of significant digits.

Don't compare floats for equality. It never quite works the way you want.

It fails on computers for the same reason it fails in decimal. If you represent 1/3 is .33333 then 3 * (1/3) is not equal to 1. If you represent 2/3 as .66667, then 2/3 - 1/3 - 1/3 is not equal to zero and 2 * (1/3) is not equal to (2/3). If you represent 2/3 as .66666, then 2/3 + 1/3 is not equal to 1.

So comparing floats for equality is going to fail in all kinds of horrible and unpredictable ways.

The gory details are explained in What Every Computer Scientist Should Know About Floating-Point Arithmetic .

my first guess is that the output function (debug) is rounding the values, which internally are stored to much higher precision...

I actually have some code (Python not PHP) that deals with lat/lons as well, and what I ended up doing (this is far from new, and applicable to many situations) is to define a smallish number, say 1e-5 (1/100000) and test for equality by taking the absolutre value of the coords difference. AIf it is less than this small number they are considered equal.

something like

constant TINY = 1e-6

if ( abs(lat1 - lat2) < TINY )
    // they are equal
else
    // they are not equal

HTH

Edit - DEF read the text David linked you to...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM