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@gmail.com <mailto:lorgandon@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 -------------------------