As per Aahz's suggestion, I'm moving this discussion here, from Python-Dev. (Thanks Aahz!)
Mark Dickinson wrote:
On Thu, Mar 13, 2008 at 4:20 AM, Imri Goldberg <firstname.lastname@example.org mailto:email@example.com> wrote:
My suggestion is to do either of the following: 1. Change floating point == to behave like a valid floating point comparison. That means using precision and some error measure. 2. Change floating point == to raise an exception, with an error string suggesting using precision comparison, or the decimal module.
I don't much like either of these; I think option 1 would cause a lot of confusion and difficulty---it changes a conceptually simple operation into something more complicated.
As for option 2., I'd agree that there are situations where having a warning (not an exception) for floating-point equality (and inequality) tests might be helpful; but that warning should be off by default, or at least easily turned off.
As I said earlier, I'd like static checkers (like Python-Lint) to catch this sort of cases, whatever the decision may be.
Some Fortran compilers have such a (compile-time) warning, I believe. But Fortran's users are much more likely to be writing the sort of code that cares about this.
Since this change is not backwards compatible, I suggest it be added only to Python 3.
It's already too late for Python 3.0.
Still, I believe it is worth discussing.
3. Programmers will still need the regular ==: Maybe, and even then, only for very rare cases. For these, a special function\method might be used, which could be named floating_exact_eq.
I disagree with the 'very rare' here. I've seen, and written, code like:
if a == 0.0: # deal with exceptional case else: b = c/a ...
or similarly, a test (a==b) before doing a division by a-b. That one's kind of dodgy, by the way: a != b doesn't always guarantee that a-b is nonzero, though you're okay if you're on an IEEE 754 platform and a and b are both finite numbers.
While checking against a==0.0 (and other similar conditions) before dividing will indeed protect from outright division by zero, it will enlarge any error you will have in the computation. I guess it would be better to do the same check for 'a is small' for appropriate values of 'small'.
Or what if you wanted to generate random numbers in the open interval (0.0, 1.0). random.random gives you numbers in [0.0, 1.0), so a careful programmer might well write:
while True: x = random.random() if x != 0.0: break
(A less fussy programmer might just say that the chance of getting 0.0 is about 1 in 2**53, so it's never going to happen...)
- what should x == x do?
If suggestion no. 1 is accepted, always return True. If no. 2 is accepted, raise an exception. Checking x==x is as meaningful as checking x==y.
- what should
1.0 in set([0.0, 1.0, 2.0])
3.0 in set([0.0, 1.0, 2.0])
Actually, one of the reasons I thought about this subject in the first place, was dict lookup for floating point numbers. It seems to me that it's something you just shouldn't do. As for your examples, I believe these two should both raise an exception. This is even worse than normal comparison - here you are checking against the hash of a floating point number. So if you do that in the current implementation, there's a good chance you'll get unexpected results. If you do that given the implementation of suggestion 1, you'll have a hard time make set work.
------------------------- Imri Goldberg www.algorithm.co.il/blogs www.imri.co.il ------------------------- Insert Signature Here -------------------------
My suggestion is to do either of the following: 1. Change floating point == to behave like a valid floating point comparison. That means using precision and some error measure
There are two ways:
1. python users have to know, that representation of float has some problems
2. python users must not care about internal float representation
Solution "2." is not good, because someday somebody will complain, that computer calculations are not accurate (some scientist who was not willing about learning how computer stores floats).
It is better to choose "1." -- beginers will have to accept that computer is not able to store every real number, because floats are stored as binary numbers. Maybe operator "==" for floats should be deprecated, and people should use something like "!~" or "=~", and they should be able to set precission for float numbers?