程序没有输入if语句
在我的python程序中,没有输入if语句。我已将代码简化为以下内容:程序没有输入if语句
x = -5
while x < 5:
if (x == 0):
print 0
x += .01
此程序不输出任何内容。
但是,将最后一行更改为x + = .5会使程序输出0.问题是什么?
浮点数表示可能不够准确。你不应该测试零相等性,而应该使用一些东西
if (abs(x) < 1E-10) ...
和'abs(x - y)ε'一般来说,其中'x'和'y'是您正在比较的值,而'epsilon'是一个小于您所关心的误差范围的小数字。 – delnan
虽然这个修复很烦人。例如,如果我想在零点以外的地方使用,如果我想在.05的话,就必须使用.04999
不幸的是,“修复”是不可能的,因为“等于”对于不同的人来说可能意味着完全不同的东西。请注意,python的人都知道这一点,并提供解释:http://docs.python.org/tutorial/floatingpoint.html – drozzy
这是一个四舍五入的问题 - 十进制值不能完全以二进制表示的,所以X从未恰好等于0.0000000000 ....
尝试if -0.001 < x < 0.001:
BTW更换if (x == 0):
,括号是一个不必要的python if
声明。
编辑: 打印出来-1和1之间的值在0.01示出了该步骤的话 - 其中零应该是它打印7.52869988574e-16。
_有些十进制值可以用二进制精确表示。 “0.1”不是这些值中的一个。 – agf
@agf:是的,我应该做得更清楚。这就是为什么0.5工作,但0.1不工作 - 0.5在二进制中完全可以表示。 –
在二进制中,.01没有确切的表示,但是.5没有。
如果你将1/3代表为.333333,并且一直添加1/3直到达到1,那么这与你在十进制中遇到的问题是一样的。三次添加之后,您将拥有.999999,它不完全等于1.
Don't compare non-integers for equality除非你正确理解这样做的规则,并100%确定你的情况是可以工作的规则之一。
-0.01
7.52869988574e-16
0.01
我建议你说X> -.001和X < 0.001或排序
其他人所指出的问题与浮点数是不能准确地表示值的东西。如果你需要一些确切十进制表示,你可以使用Decimal
类:
from decimal import Decimal
x = Decimal(-5)
while x < 5:
if (x == 0):
print 0
x += Decimal(".01")
这将打印0
如您所愿。
注意使用字符串作为增量。如果您使用的是Decimal(.01)
,则会出现与0.01的精确表示相同的问题,因为您正在从浮点数转换而已失去准确性,所以班级不允许这样做。
这是正确的做法。 OP不应该对float类型进行任何科学计算。 – patrys
看看打印声明的力量...
让我们插入一个打印语句...
x = -5
while x < 5:
if (x == 0):
print 0
x += .01
print x
运行该程序,并围绕0检查输出揭示了问题:
...
-0.13
-0.12
-0.11
-0.1
-0.0900000000001
-0.0800000000001
-0.0700000000001
-0.0600000000001
-0.0500000000001
-0.0400000000001
-0.0300000000001
-0.0200000000001
-0.0100000000001
-6.23077978101e-14
0.00999999999994
0.0199999999999
0.0299999999999
0.0399999999999
0.0499999999999
0.0599999999999
0.0699999999999
0.0799999999999
0.0899999999999
0.0999999999999
0.11
0.12
0.13
...
哦,孩子,这是从来没有实际上等于零!
解决方案:
-
使用整数。最可靠的。
x = -500 # times this by a 100 to make it an integer-based program while x < 500: if (x == 0): print 0 x += 1
-
决不测试浮点运算的平等,而是使用范围:
delta = 0.00001 #how close do you need to get point = 0 #point we are interested in if (point-delta) <= x <= (point+delta): # do stuff
对于这个微小的边距,“epsilon”是一个比“delta”更好的名称选择,因为它按照约定表示无限小的微分量,通常对应于某个期望的精度。“delta”通常用作两个值之间的差异(观察期望值或当前值先前值)。不像使用i,j和k作为循环计数器那么强大,但仍然是一个很好的区别。 – PaulMcG
@PaulMcGuire:根据数学惯例,epsilon和delta都用于小数量。我认为delta实际上是一个更好的选择,因为“epsilon”在浮点运算领域具有特定的含义,这与它在这里的使用方式不同。一个更好的名字将是'comparisonThreshold',然而=) –
@StephenCanon:你确定吗?我的工程类都使用epsilon来实现这个目的(也许这是一个“工程师说epsilon,科学家说delta”的东西)。一个“浮点epsilon”和“浮点三角洲”的快速谷歌搜索似乎为“epsilon”增加了更多的点击量,并且前几名都描述了它仅用于此目的。即使是“每个计算机程序员......”的引用都指的是epsilon,或者特别是“机器epsilon”,它是FPU中最小的可区分的差异。你在考虑什么是“FP算术领域的具体含义”? – PaulMcG
要精确到您的查询,浮点数被存储在计算机硬件二进制(基2)分数。所以,即使你在变量中存储了像0.01这样的浮点数,计算机也会最终将其转换为相应的二进制值。为方便起见,0.01浮点转换为二进制:
0.01 * 2 = 0.02 [0]
0.02 * 2 = 0.04 [0]
0.04 * 2 = 0.08 [0]
0.08 * 2 = 0.16 [0]
0.16 * 2 = 0.32 [0]
0.32 * 2 = 0.64 [0]
0.64 * 2 = 1.28 [0]
0.28 * 2 = 0.56 [0]
0.56 * 2 = 1.12 [1]
...
这种计算将是过于冗长显示在这里完全及可能不会在所有的结束。但我想在此陈述的事实是,大多数小数不能完全转换成二进制分数。因此,您存储的小数点将近似于机器中存储的二进制浮点数(显然不能存储非常长的二进制值)。所以当计算完成后,你肯定不应该期望精确的浮动值。将x + = 0.01放入代码就是这种情况。 0.5至它然而转换的二进制等效值将给出:
0.5 * 2 = 1.0 [1]
所以0.5浮子的二进制等效为0.1。因为它在您的机器中完全以二进制表示。你会得到确切的结果。
它与你的代码或python无关。这只是计算机硬件的工作方式:)
您可能想阅读[每位计算机科学家应了解的浮点算术知识](http://download.oracle.com/docs/cd/E19957-01/806 -3568/ncg_goldberg.html) – Dirk