【问题标题】:Python round off error [duplicate]Python舍入错误[重复]
【发布时间】:2013-04-02 13:29:11
【问题描述】:

我只是使用 python 作为计算,我看到了这个

Python 2.7.3 (default, Aug  1 2012, 05:14:39) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 62 * 41.2 * 2 / 250
20.435200000000002
>>> 62 * 4.12 * 2 / 25
20.4352
>>>

只是为了确保我通过 gcc 触发了以下代码,但这并没有向我显示上述行为。我知道这可能是四舍五入的东西,但它应该是统一的。为什么python在数学上不应该存在尾随的00000000002时加起来。

C/C++ 代码

#include <stdio.h>
int main () {
  printf ("%lf %lf \n", 62 * 41.2 * 2 / 250, 62 * 4.12 * 2 / 25);
}

结果

20.435200 20.435200

如果有人对他们属于某些发动机排量计算比较的特定数字感到好奇:)

【问题讨论】:

标签: python python-2.7


【解决方案1】:

您将接触到处理二进制浮点数的常见怪事;这些是大多数计算机语言所共有的。不同的输出舍入策略可以隐藏这些问题,但它们仍然存在。理解这些的通常参考是"What Every Computer Scientist Should Know About Floating-Point Arithmetic",但在"Floating Point Arithmetic: Issues and Limitations"也有一个Python特定指南

Python 有几个解决方案可用于在需要时获得更准确的结果。第一个是decimal module,它使用十进制数而不是二进制数。

>>> from decimal import Decimal
>>> Decimal(62) * Decimal("41.2") * Decimal(2) / Decimal(250)
Decimal('20.4352')
>>> Decimal(62) * Decimal("4.12") * Decimal(2) / Decimal(25)
Decimal('20.4352')

还有 fractions module 跟踪单独的分子和分母,因此可以表示任何可能的分数。

>>> from fractions import Fraction
>>> Fraction("41.2")
Fraction(206, 5)
>>> Fraction(62) * Fraction("41.2") * Fraction(2) / Fraction(250)
Fraction(12772, 625)
>>> Fraction(62) * Fraction("4.12") * Fraction(2) / Fraction(25)
Fraction(12772, 625)
>>> float(Fraction(12772, 625))
20.4352

【讨论】:

    【解决方案2】:

    尝试使用十进制

    >>> from decimal import Decimal
    >>> dec = Decimal('41.2')
    >>> 62 * dec * 2 / 250
    Decimal('20.4352')
    

    请注意,您必须使用字符串作为参数。如果你使用 float 作为参数,它会失败。

    >>> dec1 = Decimal(41.2)
    >>> dec2 = Decimal('41.2')
    >>> dec1 == dec2
    False
    >>> print dec1, dec2
    41.2000000000000028421709430404007434844970703125 41.2
    

    【讨论】:

      【解决方案3】:

      在 python 中也使用print

      In [87]: print 62 * 41.2 * 2 / 250
      20.4352
      
      In [88]: print 62 * 41.2 * 2 / 25
      204.352
      

      Python shell 使用 repr 来显示输出,这就是为什么你会得到那个奇怪的输出:

      In [89]: print repr(62 * 41.2 * 2 / 250)
      20.435200000000002
      

      print 使用str

      In [90]: print str(62 * 41.2 * 2 / 250)
      20.4352
      

      【讨论】:

        【解决方案4】:

        别担心,C 实际上也是如此,只是因为显示的数字太少而没有打印它:

        #include <stdio.h>
        int main () {
            printf ("%.16lf %.16lf \n", 62 * 41.2 * 2 / 250, 62 * 4.12 * 2 / 25);
        }
        

        给予

        20.4352000000000018 20.4351999999999983
        

        【讨论】:

          【解决方案5】:

          除了@Ashwini Chaudhary 的回答,

          问题:

          为什么在数学上不应该存在尾随的 00000000002 时,python 会加起来

          答案:

          因为机器中的值准确。这不是 Python 中的错误,也不是您的代码中的错误。您将在所有支持二进制浮点运算的语言中看到完全相同的问题。但是,不同的语言可能会以不同的方式显示(四舍五入)。

          试试这个:

          0.1 + 0.2
          

          你会得到

          0.30000000000000004
          

          这是因为0.1 不能精确地以二进制形式表示。在基数 2 或二进制中,0.1 是无穷大的重复数字

          0.0001100110011001100110011001100110011001100110011...
          

          因此,Python 决定改为四舍五入。

          我建议你阅读更多here

          【讨论】:

          • 它是“精确的”,它不仅仅是十进制,因此许多十进制值会出现舍入错误。
          猜你喜欢
          • 2011-08-25
          • 2016-01-23
          • 2011-08-21
          • 1970-01-01
          • 2011-11-22
          • 2020-01-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多