Python2.7小于比较运算符逻辑疑问:代码执行结果不符预期求助
问题根源:浮点数的精度误差
你遇到的这个问题其实是浮点数二进制表示的精度限制导致的,这在Python(不管2.7还是3.x)里都是常见的“坑”,不是代码逻辑写错了,而是计算机存储小数的方式带来的意外。
为什么会出现2.2?
先看你的循环逻辑:当P < 2.0时,执行P += 0.2;否则执行P += 2.0。按预期,当P累加到2.0时,应该进入elif分支直接跳到4.0,但实际却又执行了一次P += 0.2,得到2.2——这是因为你看到的“2.0”并不是精确的2.0。
计算机用二进制存储浮点数,而像0.2这样的十进制小数,在二进制里是无限循环的(类似十进制里的1/3=0.333...)。每次累加0.2时,都会引入微小的误差,多次累加后,误差会累积:
比如,当你从0.6开始,累加6次0.2后,理论上是0.6 + 6*0.2 = 1.8,再加一次0.2应该是2.0,但实际存储的是一个非常接近2.0但略小于2.0的数(比如1.9999999999999996)。
当代码判断P < 2.0时,这个略小的数会被判定为True,所以会再次进入if分支:打印这个看起来像2.0的数,然后再加0.2,得到2.1999999999999997——也就是你看到的2.2。
验证这个误差
你可以修改代码,用repr(P)代替print(P),这样就能看到浮点数的精确存储值:
def f(): P = 0.6 while P <= 4.0: if P < 2.0: print(repr(P)) P += 0.2 print(repr(P)) print("-") elif P < 10.0: P += 2.0
运行后,你会看到最后几次的输出大概是:
1.8 2.0 - 1.9999999999999996 2.1999999999999997 -
这里的1.9999999999999996就是那个被print显示为2.0的“假2.0”,它确实小于2.0,所以触发了额外的一次累加。
怎么解决这个问题?
有几种常见的方法:
- 使用整数模拟十进制运算:把所有数值乘以10,用整数计算(比如0.6变成6,0.2变成2,2.0变成20),最后输出时再除以10,这样就能避免浮点数误差:
def f(): P = 6 # 代表0.6 while P <= 40: # 代表4.0 if P < 20: # 代表2.0 print(P / 10.0) P += 2 # 代表0.2 print(P / 10.0) print("-") elif P < 100: # 代表10.0 P += 20 # 代表2.0 - 使用
decimal模块进行精确十进制计算:这个模块专门用于处理需要精确十进制表示的场景:from decimal import Decimal, getcontext def f(): # 设置足够的精度 getcontext().prec = 10 P = Decimal('0.6') while P <= Decimal('4.0'): if P < Decimal('2.0'): print(P) P += Decimal('0.2') print(P) print("-") elif P < Decimal('10.0'): P += Decimal('2.0') - 允许比较时的微小误差:如果必须用浮点数,可以在比较时加一个很小的容差,比如判断
P < 2.0 + 1e-9,这样即使有微小误差也能正确分支:def f(): P = 0.6 epsilon = 1e-9 while P <= 4.0 + epsilon: if P < 2.0 + epsilon: print(P) P += 0.2 print(P) print("-") elif P < 10.0: P += 2.0
内容的提问来源于stack exchange,提问作者Jelle V
相关产品推荐
相关产品推荐

