Python:奇怪的浮点数学结果

Python:奇怪的浮点数学结果,python,math,while-loop,floating-point,modulo,Python,Math,While Loop,Floating Point,Modulo,-20.0 我希望这个数字最终会以9.0结束这个while循环,但不知何故它变成了-20.0。请注意,若我将number改为9.2,它的工作原理和我预期的一样,变成了9.0。有些值可以工作,如9.0、9.7,有些值不能工作,如9.4、9.8。我不知道为什么。顺便说一下,9.8变成了-1204.5,这更奇怪。我无法解释这些结果。如果我错过了一些基本的东西,请原谅,因为我才刚刚开始学习计算机编程。这是因为浮点精度。如果在循环中打印number和number%0.5,您将得到如下结果: number

-20.0


我希望这个数字最终会以9.0结束这个while循环,但不知何故它变成了-20.0。请注意,若我将number改为9.2,它的工作原理和我预期的一样,变成了9.0。有些值可以工作,如9.0、9.7,有些值不能工作,如9.4、9.8。我不知道为什么。顺便说一下,9.8变成了-1204.5,这更奇怪。我无法解释这些结果。如果我错过了一些基本的东西,请原谅,因为我才刚刚开始学习计算机编程。

这是因为浮点精度。如果在循环中打印
number
number%0.5
,您将得到如下结果:

number = 9.3

while number % 0.5 != 0:
    number -= 0.1

print number
number
达到-20时,解决方案是精确的:

9.2 0.2
9.1 0.1
9.0 1.7763568394e-15  # Not equal to 0!
8.9 0.4
8.8 0.3
8.7 0.2
8.6 0.1
8.5 3.5527136788e-15  # Still different from 0!
...
您应该做的是,检查结果是否足够小,而不是检查0是否相等:

结果将是
9.0


但是,如果您想要一个不涉及循环的更清洁的解决方案,这将始终有效:

EPSILON = 0.0001
number = 9.3
while number % 0.5 > EPSILON:
    number -= 0.1
print number

这就是问题所在。请尝试改用
分数
模块。或者可能是
十进制
。不,您应该首先避免累加舍入。@tmyklebu我不同意:可能OP在循环中做了其他事情,而不是简单的减法,需要临时值。在任何情况下,用一个完全不同的解决方案来回答也无助于他理解问题。尽管你不同意,但不要提倡一个基于与任意选择的ε进行比较的破碎的解决方案。您可以对重复减法进行舍入误差分析,以证明epsilon的特定(更严格)选择是正确的,也可以完全避免舍入。另外请注意,如果0.1被一个浮点数表示法大于用户天真期望值的数字替换,则您的方法可能会中断。@tmyklebu用更简洁的一行代码编辑了我的答案
EPSILON = 0.0001
number = 9.3
while number % 0.5 > EPSILON:
    number -= 0.1
print number
import math
number = 0.5 * math.floor(2.0 * number)