在 Python 2.5 到 2.7 中,小数相除会产生无效结果
在彻底阅读了 Python 的 decimal 模块文档之后,我仍然发现自己对除法时会发生什么感到困惑十进制。
在 Python 2.4.6 中(有意义):
>>> import decimal
>>> decimal.Decimal(1000) / 10
Decimal("100")
在 Python 2.5.6、Python 2.6.7 和 Python 2.7.2 中(令人费解):
>>> import decimal
>>> decimal.Decimal(1000) / 10
Decimal('0.00000-6930898827444486144')
更令人困惑的是,该结果甚至看起来都不有效:
>>> decimal.Decimal('0.00000-6930898827444486144')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/decimal.py", line 548, in __new__
"Invalid literal for Decimal: %r" % value)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/decimal.py", line 3844, in _raise_error
raise error(explanation)
decimal.InvalidOperation: Invalid literal for Decimal: '0.00000-6930898827444486144'
结果是相同的使用decimal.Decimal(1000)/decimal.Decimal(10)
,因此使用 int 作为除数不是问题。
部分问题显然与精度有关:
>>> decimal.Decimal("1000.000") / decimal.Decimal("10.000")
Decimal('0.00000-6930898827444486144')
>>> decimal.Decimal("1000.000") / decimal.Decimal("10")
Decimal('0.000200376420520689664')
但是 decimal.Decimal("1000.000")
中应该有足够的精度,以便安全地除以 10 并得到至少为在正确的球场上。
事实上,Python 的三个主要修订版都没有改变这种行为,这对我来说这不是一个错误。
我做错了什么?我缺少什么?
如何除小数(不使用 Python 2.4)?
After a very thorough read of the Python's decimal module documentation, I still find myself puzzled by what happens when I divide a decimal.
In Python 2.4.6 (makes sense):
>>> import decimal
>>> decimal.Decimal(1000) / 10
Decimal("100")
In Python 2.5.6, Python 2.6.7, and Python 2.7.2 (puzzling):
>>> import decimal
>>> decimal.Decimal(1000) / 10
Decimal('0.00000-6930898827444486144')
More confusing yet, that result doesn't even appear to be valid:
>>> decimal.Decimal('0.00000-6930898827444486144')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/decimal.py", line 548, in __new__
"Invalid literal for Decimal: %r" % value)
File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/decimal.py", line 3844, in _raise_error
raise error(explanation)
decimal.InvalidOperation: Invalid literal for Decimal: '0.00000-6930898827444486144'
The result is the same using decimal.Decimal(1000) / decimal.Decimal(10)
, so it's not an issue with using an int as the divisor.
Part of the issue is clearly around precision:
>>> decimal.Decimal("1000.000") / decimal.Decimal("10.000")
Decimal('0.00000-6930898827444486144')
>>> decimal.Decimal("1000.000") / decimal.Decimal("10")
Decimal('0.000200376420520689664')
But there should be ample precision in decimal.Decimal("1000.000")
to divide safely by 10 and get an answer that's at least in the right ballpark.
The fact that this behavior is unchanged through three major revisions of Python says to me that it is not a bug.
What am I doing wrong? What am I missing?
How can I divide a decimal (short of using Python 2.4)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
根据您的 MacPorts bug,您已经安装了 Xcode 4,并且您的 Python 2.7.2 版本是使用 clang C 编译器而不是 gcc-4.2 构建的。至少有 在 OS X 上使用 clang 进行构建的一个已知问题已在 Python 中修复2.7.2.发布。要么应用补丁,要么更好的是确保构建使用 gcc-4.2。类似于(未经测试!):
在构建之前,如果 MacPorts 不覆盖它,可能可以工作。
更新:所需的补丁现已应用于 Python 2 的 MacPorts 端口文件。请参阅 https://trac。 macports.org/changeset/87442
From your MacPorts bug, you have installed Xcode 4 and your version of Python 2.7.2 was built with the clang C compiler, rather than gcc-4.2. There is at least one known problem with building with clang on OS X that has been fixed in Python subsequent to the 2.7.2. release. Either apply the patch or, better, ensure the build uses gcc-4.2. Something like (untested!):
prior to the build might work if MacPorts doesn't override it.
UPDATE: The required patch has now been applied to the MacPorts port files for Python 2. See https://trac.macports.org/changeset/87442
仅供记录:
对于使用 clang 编译的 python 2.7.3(通过 OS X 上的 Homebrew),这似乎已修复。
Just for the record:
For python 2.7.3 compiled with clang (via Homebrew on OS X), this seems to be fixed.