-
-
Notifications
You must be signed in to change notification settings - Fork 30.2k
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
Decimal strict mode should prevent Decimal("0.89") == 0.89 #125557
Comments
Not at all: Otherwise (the signal is trapped), only equality comparisons and explicit conversions are silent. All other mixed operations raise FloatOperation."
Why do you think it's a wrong answer?! 1/10 != (binary approximation of)0.1; the 0.1 can't be represented exactly as binary floating-point number. See https://docs.python.org/3/tutorial/floatingpoint.html#floating-point-arithmetic-issues-and-limitations So, current behaviour seems to be consistent and well documented. Your only argument against is wrong. And this will break backward compatibility. To change things you need more arguments. Probably, this should be discussed first on https://discuss.python.org/ |
There's a more general design principle at work here (though it's not one I think I've seen articulated clearly in the docs), not related to If >>> from decimal import Decimal
>>> s = {Decimal("0.47012"), 8946670875749133.0}
>>> list(map(hash, s))
[8946670875749133, 8946670875749133] |
Perhaps, most close to documenting it is a quote from here: "When no appropriate method returns any value other than NotImplemented, the == and != operators will fall back to is and is not, respectively." It doesn't say why this default does exists, however. But I'm not sure it worth. I think this can be closed. |
The general design principle is that floating point strict mode should prevent coders from making mistakes. Sure it's not always a mistake to say >>> Decimal(0.89)
Decimal('0.89000000000000001332267629550187848508358001708984375') Decimal has lots of use cases, and a common one is to handle dollars-and-cents. If you say account.balance < amount You can run into trouble because >>> Decimal("0.89") < 0.89
True This sort of problem is flagged by turning on floating point strict mode, and the runtime will flag that statement as incorrect. The exact same argument applies to equality. For many use cases, equality between Dollar and float is a coding error, and floating point strict mode should catch it. The idea that things like sets use equality implicitly is interesting. Problem is, most people would be surprised by >>> 0.89 in set([Decimal("0.89")])
False What is the use case where equality makes sense between Decimal and float? As for breaking changes, we could introduce a new flag, StrictMode, which would do what FloatOperation does, but includes equality. |
When they are mathematically equal.
We don't loose anything, unless you apply context settings with insufficient precision:
Mark remind us above why we can't raise an exception here. So, in this case you suggest to fall back on |
I wasn't suggesting that we fall back on To your point, I ask, what is the use case for saying |
Bug report
Bug description:
Mixing Decimals and floats will often get you the wrong answer. By default, the Decimal library allows such behavior:
Fortunately, you can turn on floating point strict mode, where mixing Decimals and floats is prohibited:
HOWEVER, for some reason,
==
and!=
are allowed in floating point strict mode, and produce wrong answers:When floating point strict mode is on, why is
==
and!=
still allowed?This code would be better without the
if equality_op:
:Why are
==
and!=
allowed in floating point strict mode?CPython versions tested on:
3.12
Operating systems tested on:
Linux
The text was updated successfully, but these errors were encountered: