Python奇怪的添加bug

时间:2012-08-08 20:56:54

标签: python floating-point addition

  

可能重复:
  python - decimal place issues with floats
  Python float equality weirdness

在下面的代码中,我有一个变量percentage,它是一个浮点数。我已将其设置为if number到达10,000percentage假设为.01

# Tries to find a number that when squared and 5%'ed is still a square.

import math

print("Script has started:\n")

percentage = .1
number = 1
while number != -1:
    number = number + 1
    num_powered = number ** 2
    num_5per = num_powered * percentage
    num_5per_sqrt = math.sqrt(num_5per)
    num_list = list(str(num_5per_sqrt))
    dot_location = num_list.index(".")
    not_zero = 0
    for x in num_list[dot_location + 1:]:
        if x != "0":
            not_zero = 1
            break
    if not_zero == 0:
        print("*********************************")
        print("Map :",number)
        print("Safe-Area :",num_5per_sqrt)
        print("Percentage :",percentage)
        print("*********************************")
        input()

    if number > 10000:
              number = 0
              percentage = percentage + .01
              print(percentage)

输出:

0.11
0.12
0.13
0.14
0.15000000000000002  # Here is where it goes crazy
0.16000000000000003

4 个答案:

答案 0 :(得分:12)

来自the Python docs

  

请注意,这是二进制浮点的本质:这是不是Python中的错误,并且它不是代码中的错误(强调我的)。您将在支持硬件浮点运算的所有语言中看到相同类型的东西(尽管某些语言默认情况下可能无法显示差异,或者在所有输出模式下都显示差异)

您应该使用the decimal module

答案 1 :(得分:6)

您正在使用浮点数并且经历过representation error。特别地,0.01没有精确表示为二进制浮点数。相反,将存储非常接近但不完全等于0.01的数字。这不是一个错误。这就是浮点运算的工作方式。

您可以通过几种方式解决问题。

  • 接受结果不完全准确或
  • 将所有内容乘以100并使用整数或
  • 使用Decimal类型。

示例:

from decimal import Decimal
percentage = Decimal('0.1')
step = Decimal('0.01')
percentage += step

答案 2 :(得分:1)

浮点数没有无限精度,所以你得到这样奇怪的行为。

更好的解决方案是将百分比存储为整数,表示十分之一的百分比并递增一。

e.g:

percent_as_integer += 1

而不是

percent_as_float += 0.01

如果要显示百分比,只需执行以下操作:

print "%d.%02d" % divmod(percent_as_integer, 100)

编辑:实际上,使用十进制模块而不是另一个答案中建议的可能是更好,更pythonic的解决方案。

答案 3 :(得分:1)

如其他答案所述,这是所有当前微处理器中本机浮点数的限制。

如果您需要十进制数字的精确表示(例如,对于会计和业务应用程序),您应该使用decimal类型,而不是浮点数。您也可以使用cdecimal模块,这是十进制类型的高性能实现。

更新: 从Python v3.3开始,内置十进制模块在C。

中实现