python python十进制比较

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1062008/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 21:23:31  来源:igfitidea点击:

python decimal comparison

pythoncomparisondecimal

提问by Anurag Uniyal

python decimal comparison

python十进制比较

>>> from decimal import Decimal
>>> Decimal('1.0') > 2.0
True

I was expecting it to convert 2.0 correctly, but after reading thru PEP 327I understand there were some reason for not implictly converting float to Decimal, but shouldn't in that case it should raise TypeError as it does in this case

我期待它正确转换 2.0,但在阅读PEP 327 后,我明白有一些原因没有将浮点数隐式转换为十进制,但在这种情况下它不应该像在这种情况下那样引发 TypeError

>>> Decimal('1.0') + 2.0
Traceback (most recent call last):
  File "<string>", line 1, in <string>
TypeError: unsupported operand type(s) for +: 'Decimal' and 'float'

so does all other operator / - % // etc

所有其他运算符 / - % // 等也是如此

so my questions are

所以我的问题是

  1. is this right behavior? (not to raise exception in cmp)
  2. What if I derive my own class and right a float converter basically Decimal(repr(float_value)), are there any caveats? my use case involves only comparison of prices
  1. 这是正确的行为吗?(不要在 cmp 中引发异常)
  2. 如果我派生我自己的类并正确使用一个浮点转换器(基本上是 Decimal(repr(float_value)),有什么注意事项吗?我的用例只涉及价格比较

System details: Python 2.5.2 on Ubuntu 8.04.1

系统详细信息:Ubuntu 8.04.1 上的 Python 2.5.2

回答by Alex Martelli

Re 1, it's indeed the behavior we designed -- right or wrong as it may be (sorry if that trips your use case up, but we were trying to be general!).

Re 1,这确实是我们设计的行为——可能是对还是错(对不起,如果这会影响您的用例,但我们试图做到通用!)。

Specifically, it's long been the case that every Python object could be subject to inequality comparison with every other -- objects of types that aren't really comparable get arbitrarily compared (consistently in a given run, not necessarily across runs); main use case was sorting a heterogeneous list to group elements in it by type.

具体来说,很长时间以来,每个 Python 对象都可能与其他对象进行不等比较——不能真正比较的类型的对象会被任意比较(在给定的运行中保持一致,不一定跨运行);主要用例是对异构列表进行排序,以按类型对其中的元素进行分组。

An exception was introduced for complex numbers only, making them non-comparable to anything -- but that was still many years ago, when we were occasionally cavalier about breaking perfectly good user code. Nowadays we're much stricter about backwards compatibility within a major release (e.g. along the 2.*line, and separately along the 3.*one, though incompatibilities areallowed between 2 and 3 -- indeed that's the whole point of havinga 3.*series, letting us fix past design decisions even in incompatible ways).

只为复数引入了一个例外,使它们无法与任何东西进行比较——但这还是很多年前的事情,当时我们偶尔会傲慢地破坏完美的用户代码。现在我们主要版本中关于向后兼容性是严格得多(例如,沿着2.*线,并沿单独3.*一个,但不兼容允许2和3之间-事实上这就是整点一个3.*系列,让我们修正以往的设计甚至以不相容的方式做出决定)。

The arbitrary comparisons turned out to be more trouble than they're worth, causing user confusion; and the grouping by type can now be obtained easily e.g. with a key=lambda x: str(type(x))argument to sort; so in Python 3 comparisons between objects of different types, unless the objects themselves specifically allow it in the comparison methods, does raise an exception:

随意的比较结果证明比它们的价值更麻烦,导致用户混淆;并且现在可以轻松获得按类型分组,例如使用key=lambda x: str(type(x))参数sort; 所以在 Python 3 不同类型的对象之间的比较中,除非对象本身在比较方法中明确允许它,否则会引发异常:

>>> decimal.Decimal('2.0') > 1.2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: Decimal() > float()

In other words, in Python 3 this behaves exactly as you think it should; but in Python 2 it doesn't (and never will in any Python 2.*).

换句话说,在 Python 3 中,它的行为与您认为的完全一样;但在 Python 2 中它没有(并且永远不会在任何 Python 中2.*)。

Re 2, you'll be fine -- though, look to gmpyfor what I hope is an interesting way to convert doubles to infinite-precision fractions through Farey trees. If the prices you're dealing with are precise to no more than cents, use '%.2f' % xrather than repr(x)!-)

Re 2,你会没事的——不过,看看gmpy,我希望这是一种通过 Farey 树将双精度数转换为无限精度分数的有趣方法。如果您处理的价格精确到不超过美分,请使用'%.2f' % x而不是repr(x)!-)

Rather than a subclass of Decimal, I'd use a factory function such as

而不是 Decimal 的子类,我会使用工厂函数,例如

def to_decimal(float_price):
    return decimal.Decimal('%.2f' % float_price)

since, once produced, the resulting Decimal is a perfectly ordinary one.

因为,一旦产生,产生的 Decimal 就是一个非常普通的 Decimal。

回答by Anurag Uniyal

The greater-than comparison works because, by default, it works for all objects.

大于比较有效,因为默认情况下,它适用于所有对象。

>>> 'abc' > 123
True

Decimalis right merely because it correctly follows the spec. Whether the spec was the correct approach is a separate question. :)

Decimal正确仅仅是因为它正确地遵循了规范。规范是否是正确的方法是一个单独的问题。:)

Only the normal caveats when dealing with floats, which briefly summarized are: beware of edge cases such as negative zero, +/-infinity, and NaN, don't test for equality (related to the next point), and count on math being slightly inaccurate.

只有在处理浮点数时的正常警告,简要总结如下:注意负零、+/-无穷大和 NaN 等边缘情况,不要测试相等性(与下一点相关),并指望数学是有点不准确。

>>> print (1.1 + 2.2 == 3.3)
False

回答by Lennart Regebro

If it's "right" is a matter of opinion, but the rationale of why there is no automatic conversion exists in the PEP, and that was the decision taken. The caveat basically is that you can't always exactly convert between float and decimal. Therefore the conversion should not be implicit. If you in your application know that you never have enough significant numbers for this to affect you, making classes that allow this implicit behaviour shouldn't be a problem.

如果“正确”是一个意见问题,但 PEP 中不存在自动转换的基本原理,这就是所做出的决定。警告基本上是你不能总是在浮点数和十进制之间完全转换。因此,转换不应该是隐式的。如果您在您的应用程序中知道您永远不会有足够的重要数字来影响您,那么创建允许这种隐式行为的类应该不是问题。

Also, one main argument is that real world use cases doesn't exist. It's likely to be simpler if you just use Decimal everywhere.

此外,一个主要论点是现实世界的用例不存在。如果您只在任何地方使用 Decimal,它可能会更简单。