[Python-ideas] Way to check for floating point "closeness"?
Chris Barker
chris.barker at noaa.gov
Thu Jan 15 20:45:22 CET 2015
On Thu, Jan 15, 2015 at 9:42 AM, Ron Adam <ron3200 at gmail.com> wrote:
> The conservative, "safe" way to handle this is to just treat the error
>> function as symmetrical
>>
> What if we are not concerned with the location two points are relative to
> zero?
not sure what location two points are relative to zero means.
Or if the numbers straddle zero?
Good catch -- at least if the numbers are symmetric to zero -- i.e. a ==
-b, then they will never be "close" according to our working definition of
relative tolerance:
a = -b
err == 2*a
abs_tol = rel_tol * a
#rel_tol is small and positive
abs_tol is always smaller than a, so always smaller than the error, so
never "close".
In fact, this is true for any numbers that straddle zero:
err == abs(a,b)
abs_tol = rel_tol* max(abs(a), abs(b))
abs_tol <= err # provided 0< rel_tol < 1
So I was thinking the issues were near zero, but they actually are for any
time:
a <= 0 <= b (or b <= 0 <= a )
that is, any time they straddle or include zero.
In this case, you need an absolute tolerance defined.
Still figuring out how to use that and provide a smooth transition...
Steven, does your code address this somehow?
-Chris
>
> and always report the larger of the two relative
>
>> errors (excluding the case where the denominator is 0, in which case
>> the relative error is either 100% or it doesn't exist). Worst case, you
>> may reject some values which you should accept, but you will never
>> accept any values that you should reject.
>>
>
> Consider two points that are a constant distance apart, but moving
> relative to zero. Their closeness doesn't change, but the relative error
> in respect to each other (and zero) does change.
>
> There is an implicit assumption that the number system used and the origin
> the numbers are measured from are chosen and relate to each other in some
> expected way.
>
> When ever you supply all the numbers, like in a test, it's not a problem,
> you just give good numbers.
>
>
> Note that you would never compare to an expected value of zero.
>>>
>>
>> You *cannot* compare to an expected value of zero, but you certainly can
>> be in a situation where you would like to: math.sin(math.pi) should
>> return 0.0, but doesn't, it returns 1.2246063538223773e-16 instead. What
>> is the relative error of the sin function at x = math.pi?
>>
>>
>> relerr(a - b, expected_feet) < tolerance # relative feet from b
>>> relerr(a - 0, expected_feet) < tolerance # relative feet from zero
>>> relerr(a - b, ulp) # percentage of ulp's
>>>
>>
>> I don't understand what you think these three examples are showing.
>>
>
> A percentage of an expected distance.
>
> Error of two points compared to a specific distance.
>
> >>> relerr(5 - -5, 10)
> 0.0
>
> I think unless you use decimal, the ulp example will either be zero or
> some large multiple of ulp.
>
>
> Take a look at the statistics test suite.
>>
>
> I definitely will. :-)
>
> I'll be the first to admit
>> that the error tolerances are plucked from thin air, based on what I
>> think are "close enough", but they show how such a function might work:
>>
>> * you provide two values, and at least one of an absolute error
>> tolerance and a relative error;
>> * if the error is less than the error(s) you provided, the test
>> passes, otherwise it fails;
>> * NANs and INFs are handled apprpriately.
>>
>>
>> is_close(218.345, 220, 1, .05) # OHMs
>>> is_close(a, b, ULP, 2) # ULPs
>>> is_close(a, b, AU, .001) # astronomical units
>>>
>>>
>>> I don't see anyway to generalise those with just a function.
>>>
>>
>> Generalise in what way?
>>
>
> I meant a function that would work in many places without giving some sort
> size and tolerance hints.
>
> Given two floating point numbers and noting else, I don't think you can
> tell if they represent something that is close without assuming some sort
> of context. At best, you need to assume the distance from zero and the
> numbers used are chosen to give a meaningful return value. While that can
> sometimes work, I don't think you can depend on it.
>
>
> By using objects we can do a bit more. I seem to recall coming across
>>> measurement objects some place. They keep a bit more context with them.
>>>
>>
>> A full system of <value + unit> arithmetic is a *much* bigger problem
>> than just calculating error estimates correctly, and should be a
>> third-party library before even considering it for the std lib.
>>
>
> Yes, I agree. There are a few of them out there already.
>
> Cheers,
> Ron
>
>
>
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
--
Christopher Barker, Ph.D.
Oceanographer
Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception
Chris.Barker at noaa.gov
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20150115/b317d77d/attachment-0001.html>
More information about the Python-ideas
mailing list