【问题标题】:Python and very small decimalsPython和非常小的小数
【发布时间】:2014-02-04 04:25:23
【问题描述】:

关于在 macosx 上运行的 Python 2.7.6 的有趣事实:

你有一个非常小的数字,例如:

0.000000000000000000001

你可以表示为:

>>> 0.1 / (10 ** 20)
1.0000000000000001e-21

但是你可以看到最后的浮点错误。我们真正拥有的是这样的:

0.0000000000000000000010000000000000001

所以我们的号码有误,但没关系。问题如下:

如预期:

>>> 0.1 / (10 ** 20) == 0
False

但是,等等,这是什么?

>>> 0.1 / (10 ** 20) + 1 == 1
True

>>> repr(0.1 / (10 ** 20) + 1)
'1.0'

看起来 python 正在使用另一种数据类型来表示我的数字,因为这仅在使用第 16 位十进制数字时才会发生,依此类推。还有为什么python决定在加法时自动将我的号码转为0?我不应该处理小数部分非常小的十进制数和浮点错误吗?

我知道这个问题可能属于 浮点错误,解决方案通常是不信任浮点进行这种计算,但我想更多地了解下发生的事情引擎盖。

【问题讨论】:

标签: python floating-point


【解决方案1】:

考虑当您尝试将 7.00 和 .001 相加并且只允许使用三位数字作为答案时会发生什么。 7.001 是不允许的。你是做什么的?

在您可以返回的值中,例如 6.99、7.00 和 7.01,最接近正确答案的是 7.00。因此,当要求添加 7.00 和 .001 时,您返回 7.00。

当您要求计算机在 1e-21 和 1 附近添加一个数字时,计算机也会遇到同样的问题。它只有 53 位用于浮点值的小数部分,而 1e-21 几乎是 70 位低于 1。因此,它将正确的结果四舍五入为最接近的值,即 1,然后返回。

【讨论】:

  • 这是一个不错的答案,但如果它解释了为什么我确实可以拥有1e-21 号码,但不能拥有1 + 1e-21 号码,那就更完整了。根据您的解释,即使在添加之前,1e-21 也会四舍五入为0,但事实并非如此。我认为这里的关键是指出确实可以使用科学计数法将1e-21 表示为浮点数,但不能用1 + 1e-21 表示,因为它会导致1.000000000000000000001e-0 用科学计数法表示
  • 我有一个需要保留细节的场景 - 有没有办法做到这一点?
【解决方案2】:

浮点数的工作方式类似于科学记数法。 1.0000000000000001e-21 适合 64 位浮点允许的 53 位有效位/尾数。在其中添加1,比微小部分大许多数量级,导致次要细节被丢弃,并准确存储1

【讨论】:

  • Python 浮点数实际上是双精度数,因此您可以获得 53 位的精度。但同样适用。
  • 哦,天哪,我完全知道,感谢您纠正我。更新答案
  • 确实,这很有趣。 1e-21 确实可以在浮点上表示,但 1 + 1e-21 会导致 1.000000000000000000001e-0。将1 添加到1e-21 看起来很简单,但有点像将大象与原子混合
  • 大象和原子。我喜欢这样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多