On Tue, Jan 13, 2015 at 08:57:38PM -0600, Ron Adam wrote:
On 01/13/2015 09:53 AM, Chris Barker - NOAA Federal wrote:
[...]
I haven't thought it out yet, but maybe we could specify an absolute tolerance near zero, and a relative tolerance elsewhere, both at once. Tricky to document, even if possible.
Doesn't this problem come up at any boundary comparison, and not just zero?
No. A quick refresher on error tolerances... Suppose you have a value which should be exactly 0.5, but you calculate it as 0.51. Then the absolute error is 0.51-0.5 = 0.01, and the relative error is 0.01/0.5 = 0.02 (or 2%). But consider two values, 0.0 and 0.1. Then the absolute error is 0.1-0.0 = 0.1, and the relative error is 0.1/0.0 which is infinite. So 0.0 and -0.0 are problematic when dealing with relative errors.
So isn't the issue about any n distance from any floating point number that is less than 1 ulp? And in that regard, comparison to zero is no different than any comparison to any other floating point value?
No. 1 ULP (Unit In Last Place) is the smallest possible difference between two floats. A difference of 0 ULP means the two floats are exactly equal. How it works: in mathematics, real numbers are continuous, but floats are not. There are only 2**64 floats in Python (a C double), less if you ignore the NANs and INFs, which means we can conveniently enumerate them from -(2**64) to (2**64-1), based on the internal structure of a float. So if you convert two floats into this enumerated integer value (which is equivalent to doing a type-cast from a C double to a C long) and subtract the two ints, this gives you a measure of how far apart they are. (As Mark mentioned earlier, you have to make allowance for negative floats, also INF and NANs are problematic too.) If two values are exactly equal, their "distance apart" in ULP will be zero. A distance of 1 ULP means they are consecutive floats, they cannot possibly be any closer without being equal. A distance of 2 ULP means there is only a single float separating them, and so on. Note that ULP do not directly correspond to a numeric tolerance. For example, these pairs of values are each 1 ULP apart: 0.0 and 5e-324 1.0 and 1.0000000000000002 1e300 and 1.0000000000000002e+300 So in these three cases, 1 ULP represents numeric differences of: 0.00000000000000000000...00005 0.0000000000000002 2000000000000000000000...000.0 respectively.
Just trying to follow along,
A good resource is Bruce Dawson's blog RandomASCII, if you don't mind the focus on C++. Start here: https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-number... -- Steve