增加的浮点数不相等

5

我正在尝试运行一个有两个变量的程序,当一个变量等于另一个变量时,它执行一个函数。 在这种情况下,打印spam。 但是,出于某种原因,当我运行此程序时,我没有得到任何输出,即使我知道它们是相等的。

可能重复:
为什么十进制数无法在二进制中精确表示?
程序不进入if语句

g=0.0
b=3.0

while g < 30.0:
    if g==b:
        print "Hi"
    g+=.1
    print g, b

2
http://docs.python.org/tutorial/floatingpoint.html - jamylak
6
《计算机科学家应该了解的浮点数算术知识》(What Every Computer Scientist Should Know About Floating-Point Arithmetic)是一篇关于计算机浮点数算术的经典论文,由David Goldberg撰写。本文介绍了浮点数表示法、舍入误差以及浮点数算术中的各种陷阱和问题。对于从事计算机编程和科学计算的人来说,了解这些内容非常重要。 - Peter Graham
3个回答

9

你认为将0.0加上足够多的0.1就能得到3.0。但这些是浮点数,它们不精确。舍入误差使得值永远无法完全等于3.0。你几乎永远不应该使用 == 来测试浮点数。


1
如果您确实需要精度较高的十进制数学计算,可以使用“Decimal”模块。但是,为什么要这样做超出了OP提供的数据范围。 - tkone
在将 0.1 加 30 次后,变量 g 的实际值为 3.0000000000000013 - Kijewski
1
这是一个可行的替代方案吗:g = round(g+0.1, 1) - inspectorG4dget
2
+1 表示“几乎从不”使用 == 而不是“从不”。 - Eric Postpischil

6
一种好的方法是使用整数值进行计数(例如,通过 i 从0到300循环),并仅在使用浮点值时才缩放计数器(例如,设置 f = i * .1)。这样做,循环计数器始终是精确的,因此您可以得到确切的迭代次数,并且只有一个浮点舍入,不会从迭代累积到迭代。
循环计数器通常是整数类型,因此可以轻松地看到加法是精确的(直到达到溢出)。但是,循环计数器也可以是浮点类型,前提是您确定其值和操作是精确的。(常见的32位浮点格式可准确表示-2 24 到+2 24 的整数。超出该范围后,它没有足够的精度来准确表示整数。它不准确地表示0.1,因此您不能以0.1的增量进行计数。但是,您可以以0.5、0.25、0.375或其他适度的二的幂的小倍数的增量进行计数,这些数可以被准确表示。)

0
为了进一步解释Karoly Horvath的评论,您可以做的是选择一个非常非常小的值(我们称之为epsilon),相对于最小增量来说。假设epsilon是1.0 * 10^-6,比您的增量小五个数量级。(它可能应该基于您的浮点表示的平均舍入误差,但这是一个例子)。
然后,您需要检查g和b是否相差不到epsilon - 如果它们足够接近,以至于它们实际上是相等的,则实际上与几乎相等之间的差异是舍入误差,您正在用epsilon来近似。
请检查。
abs(g - b) < epsilon

并且你会得到几乎但又不完全相等的检查,这对大多数情况来说应该已经足够好了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接