Floating point calculations with latitudes and longitudes of varying precision
Background: I am getting long and lat as parameters for a web service. They are usually up to six decimal places. When a new request is received, I calculate the distance between the last recorded loc and long / lat in the request parameters. If the distance is greater than a certain threshold distance in miles apart, I update the current loc.
Problem: I am using geokit gem / plugin to calculate distance between locs. It is very rare for an error to appear (error at zero distance mentioned on the author's site - I am using 1.4.1 which claims the bug is fixed, but I can still see it happening with shoulders), which causes the remote computation to return something wildly imprecise when calculating the distance between two points that are identical (this happens if the user does not move). This causes the current user to be updated, which should not happen. You're probably wondering - okay if it just updates loc to be exactly the same coordinates, who cares? Well, the answer is that a bunch of other crap comes up when loc is updated, making it a topical issue.
Attempted solution: I tried to add logic to manually check if the two locs are identical before calculating the distance, and then just skip the calculation and not update if so. Input parameters are long / lat with 6 decimal precision; whereas in my database I store the values as floats which appear to only store 4 decimal places. This causes my floating point comparison to always fail and unsatisfactory locator updates keep popping up.
Phew, ok, so really the question is, how do I do this comparison? Should I truncate 2 decimal places from the incoming lat / lengths, round off one way or another so that the fourth digit is correct and then comparable? Or should I perform an "in-range" comparison (eg report_loc.long> current_loc.long -.0001 & report_loc.long <current_loc.long +.0001)? Any advice on existing ruby gems / plugins or built in functionality for this kind of thing would also be appreciated.
Here's an example of the output from the log:
[update_loc] Last location history record at lat: 41.5024, long: -81.6816 [update_loc] Current loc at lat: 41.502467, long: -81.681623 [update_loc] Distance from current loc and last loc history: 5795.10615113555 miles [update_loc] Locs not identical and distance greater than threshold, inserting new loc history [update_loc] Location update complete
source to share
A GPS receiver can provide you with a location accurate to tens of marks, but that doesn't mean the measurement is truly accurate.
Usually about 95% of the measurements are in a circle of a couple of meters, which is about the same precision as you can store with a 32-bit float.
However, you will clearly notice rounding errors when plotting the gps log like a float on the map.
Anyway, to make this comparison I would use a range instead of rounding the input value and comparing it to the database value. You won't be able to detect the smallest movements anymore, but at least you won't get false positives either.
The way you use floats to store things, you obviously don't care about millimeters or centimeters anyway.
source to share