Reputation: 7769
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?
Upvotes: 0
Views: 80
Reputation: 2403
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...
Upvotes: 0
Reputation: 839074
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.
Upvotes: 3
Reputation: 182865
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.
Upvotes: 2