【问题标题】:Rounding Problem with Python [duplicate]Python的舍入问题[重复]
【发布时间】:2011-11-22 20:04:24
【问题描述】:

可能重复:
Python rounding error with float numbers

我在 Python 中有一个舍入问题。如果我计算

32.50 * 0.19 = 6.1749999999999998

但这应该是 6.175。如果我将 6.1749999999999998 舍入 2 位小数,则它正确显示 6.18。所以我可以忍受。

但如果我计算这个:

32.50 * 0.19 * 3 = 18.524999999999999

这应该是 18.525。如果我将值 18.524999999999999 舍入两位小数,则显示 18.52。

它应该显示 18.53。我做错了什么,我该如何解决?

【问题讨论】:

  • 试试print 32.50 * 0.19 或print 32.50 * 0.19 * 3。 Python 知道如何正确显示这些浮点值。只要是这种情况,您就可以像计算机一样接近使用浮点存储的正确(十进制)值。如果您真的需要准确 答案(您不需要),请使用Decimal.decimal。
  • -1。在 StackOverflow 的搜索中输入这篇文章的标题很容易找到这个问题的答案。 -1 表示没有为此付出努力。

标签: python rounding


【解决方案1】:

我不认为这是错误的。从 Python 解释器中获取:

>>> round(18.524999999999999,2)
18.52
>>> round(6.1749999999999998,2)
6.17
>>> 

在这两种情况下,四舍五入的数字都小于 5,因此向下舍入。 18.52 和 6.17。

没错。

我不明白为什么你得到 6.18,而我得到 6.17。我正在使用 Python 3.2.2(最新版本)

【讨论】:

  • 因为他没有确切的号码,那只是他真正拥有的号码中的repr。
【解决方案2】:

你没有做错任何事,it isn't Python's fault either。有些十进制数不能精确地表示为二进制浮点数。

就像您不能将 1/3 写成十进制 (0.33333....),也不能将十进制 0.1 写成二进制 (0.0001100110011001100110011001100110011001100110011...)。

解决方案 A:

使用print 32.5 * 0.19 - 它会自动对结果进行四舍五入。

解决方案 B:

如果您确实需要这种精度,例如在使用货币值进行计算时,请使用 Decimal 模块。

解决方案 C:

使用 Python 3.2 或 Python 2.7,这将在交互式会话中自动对结果进行四舍五入。

Python 2.7.2 (default, Jun 12 2011, 14:24:46) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> 32.50 * 0.19
6.175

【讨论】:

    【解决方案3】:

    What Every Computer Scientist Should Know About Floating-Point Arithmetic.

    简而言之 - 您不应该依赖浮点数的精确值,因为它们存储在内存中的方式。

    另请参阅有关它的 python 文档 - Floating Point Arithmetic: Issues and Limitations。它包含下一段:

    例如,如果您尝试将值 2.675 舍入到小数点后两位,您会得到这个

    >>> round(2.675, 2)
    2.67

    内置 round() 函数的文档说它 舍入到最接近的值,从零舍入关系。由于 小数 2.675 正好在 2.67 和 2.68 之间,你 可能期望这里的结果是(二进制近似)2.68。 不是,因为当十进制字符串 2.675 转换为 二进制浮点数,它再次被二进制替换 近似值,其精确值为

    2.67499999999999982236431605997495353221893310546875

    由于这个近似值比 2.68 更接近 2.67,所以它是 向下舍入。

    【讨论】:

    • 虽然文档和教程都没有更新,但在 Python 2.7.4 中,round(2.675, 2) 现在将按预期提供2.68。
    • @Neftas:你提出这个主张的依据是什么?在我使用 Python 2.7.6 的机器上,round(2.675, 2) 向下舍入,正如文档中所述。自 Python 2.7.0 以来,round 算法没有任何重大变化。
    • 你是对的,@MarkDickinson。在我写这篇文章的时候,我当然试过了,但现在我新安装的 Python 2.7.3 已经完成了。所以这可能是我这边的一个错误。
    • @Neftas:好的,这是有道理的。 round 函数的历史相当混乱:它大部分在 Python 2.6 中舍入一半,总是在 Python 2.7 中舍入一半,而 在 Python >= 3.1 中,总是 将中途情况舍入到最接近的偶数结果。当然,除了底层的二进制表示之外,看起来像十进制中的中途情况并不一定是实际的中途情况。
    • 显然,你不想在代码中依赖它。对于这种划分,最好始终使用 decimal 模块(如 Python 参考中所建议的那样)。
    【解决方案4】:

    你没有做错任何事。这是由于数字的内部表示:

    例如,试试这个:

    0.1 + 0.1 +  0.1 + 0.1 +  0.1 + 0.1 +  0.1 + 0.1 +  0.1 + 0.1
    

    如果您需要更高的精度,请使用十进制表示

    【讨论】:

      【解决方案5】:
      【解决方案6】:

      使用python中的Decimal模块进行精确的浮点运算

      from decimal import Decimal, ROUND_UP
      
      value = Decimal(32.50 * 0.19 * 3)
      print (value.quantize(Decimal('.01'), rounding=ROUND_UP))
      

      Output: 18.53
      

      【讨论】:

      • 虽然他并不真正需要Decimal,他只是不明白浮点是如何工作的。
      • OP 询问如何修复它 (Decimal)。该链接还解释了为什么 OP 会出现此问题。
      【解决方案7】:

      如果您需要精确的算术,可以使用decimal 模块:

      import decimal
      D=decimal.Decimal
      
      x=D('32.50')*D('0.19')
      print(x)
      # 6.1750
      print(x.quantize(D('0.01'),rounding=decimal.ROUND_UP))
      # 6.18
      
      y=D('32.50')*D('0.19')*D('3')
      print(y)
      # 18.5250
      print(y.quantize(D('0.01'),rounding=decimal.ROUND_UP))
      # 18.53
      

      【讨论】:

      • 虽然他并不真正需要Decimal,他只是不明白浮点是如何工作的。
      • @agf:你怎么知道他需要什么?他完全有可能在处理金钱,这不应该用浮点数来做。
      • 确切的我在处理金钱,所以我会试试这个谢谢:)
      猜你喜欢
      • 2018-07-28
      • 1970-01-01
      • 1970-01-01
      • 2019-01-07
      • 2016-01-23
      • 1970-01-01
      • 1970-01-01
      • 2012-07-31
      • 1970-01-01
      相关资源
      最近更新 更多