-
-
Notifications
You must be signed in to change notification settings - Fork 29.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
float compared to decimal is silently incorrect. #46783
Comments
Within python 2.5.2: >>> from decimal import Decimal
>>> x = 3.0
>>> y = Decimal('0.25')
>>> x > y
False (expected error, as in 2.4, or True) |
Which version of 2.4 are you talking about? This line in the tests... self.assertNotEqual(da, 32.7) is there since almost 4 years ago (release 36325, and 2.4 is tagged in Anyway, this behaviour is ok, as is the following: >>> 2 < "1.9"
True |
This behavior also exists in Python 2.6. However, in Python 3 an As an aside, regardless of Python 3's behavior, there is a big |
Imri, I don't think the 3.0 model for cross-type comparisons can be Mark, this raises a question for us. Now that we have |
Making float <-> Decimal comparisons return the 'right' answer in 2.x does Are there many cases where float <-> Decimal comparisons are useful? The The current bogus comparison results also suck, but they're just one Would it be possible to raise a warning for Decimal <-> float comparisons? |
I hear you on the 2.x to 3.x transition-- I'm not really asking for My complaint is that it is silently wrong. |
I appreciate that, but I don't see any good solution. Yes, it would be I think the best we can do would be to add a warning for float <-> Decimal |
I think "the best we can do" is return valid comparison results between |
The next to last sentence should have read "and, we are not The gist of the idea is that in 2.x, we do have cross-type ordering |
What about Decimal <-> Fraction comparisons? |
It's not a priority for me though it's not an unreasonable thing to do. If you do decide to do fractions too, the responsibility should be with |
Here's a patch. I'm still not 100% convinced this is a good idea. Part of my objection is |
On the other hand, if it's true that mixed-type comparisons are generally The patch still needs docs. |
Urk. That patch produces horrible results when comparing Fractions and Python 2.7a0 (unknown, Mar 21 2009, 17:59:48)
[GCC 4.0.1 (Apple Inc. build 5490)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from fractions import Fraction
>>> from decimal import Decimal
>>> Decimal('2.5') == Fraction(5, 2)
True
>>> Decimal('1.1') == Fraction(11, 10)
False Either both results should be True (if comparisons between Fractions and It looks like what happens is that the Fraction comparison converts the |
One more consideration: if Decimal('2.5') == 2.5 is True, should we also |
I'll look at this more later today. |
Removing easy keyword, since I don't think it applies here. The problem here is hashing: either we break the rule that For the latter, the least invasive way to do it would be if x == Decimal.from_float(x.to_float()):
return hash(x.to_float())
[rest of hash method here] The builtin float() (which converts a Decimal to a string The bottom line: getting a correctly-rounded |
Mark, I looked at your patch again and think we should support relaxed The only thing that I don't like about it is that you can't do the usual |
Mark, any thoughts? I would like to apply this patch for ordering |
On Fri, Apr 17, 2009 at 3:45 AM, Raymond Hettinger
Hi Raymond, Sorry for not responding to this sooner. I'll post something to IOW I wouldn't do this if it were just up to me, but not going Mark |
I'm not seeing the downside. This gives better answers than it does now |
The downside is the potential confusion arising from |
Unassigning myself. Does anyone beside Raymond and me have strong opinions about how/whether |
Closing since no one seems interested. |
I'm interested. I just had already said my peace and didn't know my |
Just closed bpo-7323 as a duplicate of this one. I think this issue is worth reopening: with the backport of the py3k I'd still be uncomfortable with allowing Decimal-to-float comparisons in |
Expressions like "Decimal('100.0') < .01" being silently wrong (True!) is *very* dangerous behavior, it should raise exception like any other Decimal-float operation, and hopefully will be back-ported to 2.7. Eg: 3rd party module kinterbasdb, which provides access to Firebird database, returns floats from firebird large-int types (eg NUMERIC 18,2) in versions of kinrebasdb 3.2 or less, but in versions 3.3+ kinterbasdb retrieves large-int as type Decimal. This means if python/kinterbasdb users upgrade kinterbasdb they must be aware of this python bug, because all existing code must be inspected for "(retrieved Decimal value) compare (float)" statements, which before upgrade were Ok (retrieved float value) compare (float)) statements. I'm new to this tracker, I hope this simply is added as an additional comment & squawk of dismay to the "float compared to decimal is silently incorrec" issue. |
I'll try to find time to look at this again before 2.7 beta. |
So here's the plan for trunk. The big question is: what should be done for py3k? For trunk:
For py3k, the obvious options are: (A) adopt the above changes, or (B) keep Decimal and float non-comparable (as currently). In this case, a Decimal-to-float comparison in trunk should probably raise a DeprecationWarning. (Note that DeprecationWarnings are now silent by default, so such a warning wouldn't impact end-users much.) |
I'm new to this thread, so I hope I didn't miss anything that has been "If you want to implement a type for which only a limited set of comparisons makes sense (e.g. == and !=, but not < and friends), directly raise TypeError in the rich comparison function." I just tried that in the 2.7 version of cdecimal, and it works well: >>> from cdecimal import *
>>> Decimal(9) < 2.5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: conversion from float to Decimal is not supported |
Stefan: the problem is backwards compatibility. In 2.6 it's possible to sort a heterogeneous list that contains both Decimal instances and floats. The resulting order may not be particularly meaningful, but for some applications that doesn't matter. If we make a Decimal-to-float comparison raise TypeError for 2.7 then sort will raise a TypeError where it used to work, so it's a potential code-breaking change. We could deprecate: raise a warning in 2.7 and make it a TypeError in 2.8, but since 2.8 currently seems unlikely to happen that would be a bit pointless. |
Here's a patch:
Still open: should this change be forward ported to py3k? If not, then these comparisons should produce a DeprecationWarning. |
For anyone interested, there's an ongoing python-dev discussion about how to resolve this at http://mail.python.org/pipermail/python-dev/2010-March/098437.html |
Float-to-decimal comparisons have been fixed, and the Decimal hash function changed so that numerically equal Decimal and float instances hash equal, in r79583. The idea of raising an exception for float<->Decimal comparisons was discarded partly for backwards compatibility reasons, and partly because having __eq__ raise an exception causes difficulties for sets and dicts: for example, if equality checks between floats and Decimals raised an exception then '{-1.0, Decimal(-3)}' would give a valid set (the two values have different hashes, so the Decimal.__eq__ method is never invoked), but '{-1.0, Decimal(-2)}' would raise an exception (because the two set elements have equal hashes, so Decimal.__eq__ is invoked in order to determine whether the two elements are equal or not). (General principle: if x and y are hashable, x == y should never raise an exception.) This is still only a partial fix: comparisons between Decimal and Fraction instances still behave oddly. This seems less likely to cause problems in real-life code, though. The changes needed to make Decimal <-> Fraction comparisons correct are too intrusive and not yet well tested enough to make it into 2.7. (See bpo-8188). As discussed on python-dev, I'll forward port this to py3k; with any luck, py3k will also grow valid comparisons for Decimal <-> Fraction. |
Merged to py3k in r79668. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: