[Python-ideas] [Python-Dev] The Case Against Floating Point ==

Imri Goldberg lorgandon at gmail.com
Thu Mar 13 19:38:12 CET 2008



Mark Dickinson wrote:

> (with apologies for the random extra level of quoting in the below...)
>  
>
>     On Thu, Mar 13, 2008 at 11:09 AM, Imri Goldberg
>     <lorgandon at gmail.com <mailto:lorgandon at gmail.com>> wrote:
>
>         As I said earlier, I'd like static checkers (like Python-Lint)
>         to catch
>         this sort of cases, whatever the decision may be.
>
>  
> Hmm.  Isn't that tricky?  How does the static checker decide
> whether the objects being compared are floats?  I guess one could
> be content with catching some cases where the operands to ==
> are clearly floats...  Wouldn't you have to have run-time warnings
> to be really sure of catching all the cases?
>

Yes. Writing a static-checker for Python is tricky in any case. For the 
sake of this discussion, it might be useful to refer to some 'ideal' 
static checker. This will allow us to better define what is the desired 
behavior.

>
>         > It's already too late for Python 3.0.
>         Still, I believe it is worth discussing.
>
>
>  
> Sure.  I didn't mean that to come out in quite the dismissive way it 
> did :).
> Apologies.  Maybe a PEP aimed at Python 4.0 is in order.  If you're open
> to the idea of just having some way to enable warnings, it could be
> much sooner.
>

I think that generating a warning (by default?) is a strong enough 
change in the right direction, so we should add that as another option. 
(Was also suggested in a comment on my blog.)

>
>         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'.
>
>  
> Still, a check for 0.0 is good enough in some cases:  if a is tiny, the
> large intermediate values may appear and then disappear happily
> before giving a sensible final result.  These are usually the sort
> of cases where just having division by 0.0 return an infinity
> would have "just worked" too (making the whole "if" redundant), but
> that's not (currently!) an option in Python.
>
> It's a truism that floating-point equality tests should be avoided, but
> it's just not true that floating-point equality testing is *always* wrong,
> and I don't think that Python should make it so.
>

Alright, that's why in my original suggestion, I proposed a function for 
'old-style' comparison.
It still seems to me that in most cases you are better off doing 
something other than using the current ==.

A point I'm not sure of though, is what happens to other comparison 
operators, namely,
<=, <, >, >=. If they retain their original meaning than <= and >= 
become at least a bit inconsistent.
I'll be glad to hear more opinions about this.


>         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.
>
>  
> So your proposal would presumably include making
>
>   x in dict
>
> and
>
>   x not in dict
>
> errors for any float x, regardless of the contents of the dictionary
> (or list, or set, or frozenset, or...) dict?
>
> What would you do about Decimals? A Decimal is just another
> floating point format (albeit base 10 instead of base 2); so
> presumably all these warnings/errors should apply equally
> to Decimal instances?  If not, why not?
>

This last note gave me pause. I still need to think more about this, but 
here are my thoughts so far:

1. Decimal's behavior might be considered even more inconsistent - the 
precision applies to arithmetical operations, but not to comparisons.
2. As a result, it seems to me that decimal's behavior might also be 
changed.
It needn't be the same change as regular floating point though - decimal 
behavior might follow suggestion 1, while regular floating points might 
follow suggestion 2. (I see no point in it being the other way around 
though.)
3. Usage in containers depending on __hash__ should change according to 
how == behaves for decimals. If == raises an a warning/exception, so 
should "x in {..}". If == will be changed to work according to precision 
for decimals, then usage in containers will be (very) problematic, 
because of context changes. (Consider what happens when changing the 
precision.)
4. Right now, I would avoid using decimal or regular floating points in 
such containers. The results are just not predictable enough. Using the 
'ideal static-checker' mentioned above, I'd say that any such use should 
result in a warning.

In any case, there might be a place for a way to do floating point 
comparisons in a 'standard' manner.

> I'm not trying to be negative here---as Aahz says, this is an
> interesting idea;  I'm just trying to understand exactly how
> things might work.
>
> Mark

Sure, so do I.

Cheers,
Imri.


-------------------------
Imri Goldberg
www.algorithm.co.il/blogs
www.imri.co.il
-------------------------
Insert Signature Here
-------------------------



More information about the Python-ideas mailing list