Floating point equality [was Re: What exactly is "exact" (was Clean Singleton Docstrings)]
Marko Rauhamaa
marko at pacujo.net
Wed Jul 20 09:54:55 EDT 2016
Steven D'Aprano <steve at pearwood.info>:
> I am not a good computer scientist. But Bruce Dawson *is* a good
> computer scientist:
>
> https://randomascii.wordpress.com/2014/01/27/theres-only-four-billion-f
> loatsso-test-them-all/
>
> Quote:
>
> Conventional wisdom says that you should never compare two floats
> for equality – you should always use an epsilon. Conventional
> wisdom is wrong.
>
> I’ve written in great detail about how to compare floating-point
> values using an epsilon, but there are times when it is just not
> appropriate. Sometimes there really is an answer that is correct,
> and in those cases anything less than perfection is just sloppy.
>
> So yes, I’m proudly comparing floats to see if they are equal.
The point of view in the linked article is very different from that of
most application programming that makes use of floating-point numbers.
Yes, if what you are testing or developing is a numeric or mathematical
package, you should test its numeric/mathematical soundness to the bit.
However, in virtually any other context, you have barely any use for
a floating-point equality comparison because:
1. Floating-point numbers are an approximation of *real numbers*. Two
independently measured real numbers are never equal because under
any continuous probability distribution, the probability of any
given real number is zero. Only continuous ranges can have nonzero
probabilities.
2. Floating-point numbers are *imperfect approximations* of real
numbers. Even when real numbers are derived exactly, floating-point
operations may introduce "lossy compression artifacts" that have to
be compensated for in application programs.
What you have to do exactly to compensate for these challenges depends
on the application, and is very easy to get wrong. However, if an
application programmer is using == to compare two floating-point data
values, it is almost certainly a mistake.
> Or you might be using a language like Javascript, which intentionally
> has only floats for numbers. That's okay, you can still perform exact
> integer arithmetic, so long as you stay within the bounds of ±2**16.
>
> Not even in Javascript do you need to write something like this:
>
> x = 0.0
> for i in range(20):
> x += 1.0
>
> assert abs(x - 20.0) <= 1e-16
Correct because Javascript makes an exactness guarantee of its integers
(I imagine).
In Python, I think it would usually be bad style to rely even on:
1.0 + 1.0 == 2.0
It is very difficult to find a justification for that assumption in
Python's specifications. What we have:
Floating-point numbers are represented in computer hardware as base 2
(binary) fractions.
<URL: https://docs.python.org/3/tutorial/floatingpoint.html>
almost all platforms map Python floats to IEEE-754 “double precision”
<URL: https://docs.python.org/3/tutorial/floatingpoint.html#represent
ation-error>
numbers.Real (float)
These represent machine-level double precision floating point
numbers. You are at the mercy of the underlying machine
architecture (and C or Java implementation) for the accepted range
and handling of overflow.
<URL: https://docs.python.org/3/reference/datamodel.html#the-standar
d-type-hierarchy>
I believe a Python implementation that would have:
1.0 + 1.0 != 2.0
would not be in violation of Python's data model. In fact, even:
1.0 != 1.0
might be totally conformant. For example, we could have a new underlying
real-number technology that stored the value in an *analogous* format
(say, an ultra-precise voltage level) and performed the calculations
using some fast, analogous circuitry.
Marko
More information about the Python-list
mailing list