程序没有输入if语句

问题描述:

在我的python程序中,没有输入if语句。我已将代码简化为以下内容:程序没有输入if语句

x = -5 
while x < 5: 
    if (x == 0): 
     print 0 
    x += .01 

此程序不输出任何内容。

但是,将最后一行更改为x + = .5会使程序输出0.问题是什么?

+7

您可能想阅读[每位计算机科学家应了解的浮点算术知识](http://download.oracle.com/docs/cd/E19957-01/806 -3568/ncg_goldberg.html) – Dirk

浮点数表示可能不够准确。你不应该测试零相等性,而应该使用一些东西

if (abs(x) < 1E-10) ... 
+0

和'abs(x - y)ε'一般来说,其中'x'和'y'是您正在比较的值,而'epsilon'是一个小于您所关心的误差范围的小数字。 – delnan

+0

虽然这个修复很烦人。例如,如果我想在零点以外的地方使用,如果我想在.05的话,就必须使用.04999 gsingh2011

+0

不幸的是,“修复”是不可能的,因为“等于”对于不同的人来说可能意味着完全不同的东西。请注意,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。

+3

_有些十进制值可以用二进制精确表示。 “0.1”不是这些值中的一个。 – agf

+0

@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的精确表示相同的问题,因为您正在从浮点数转换而已失去准确性,所以班级不允许这样做。

+0

这是正确的做法。 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 
... 

哦,孩子,这是从来没有实际上等于零!

解决方案:

  1. 使用整数。最可靠的。

    x = -500 # times this by a 100 to make it an integer-based program 
    while x < 500: 
        if (x == 0): 
        print 0 
        x += 1 
    
  2. 决不测试浮点运算的平等,而是使用范围:

    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 
    
+0

对于这个微小的边距,“epsilon”是一个比“delta”更好的名称选择,因为它按照约定表示无限小的微分量,通常对应于某个期望的精度。“delta”通常用作两个值之间的差异(观察期望值或当前值先前值)。不像使用i,j和k作为循环计数器那么强大,但仍然是一个很好的区别。 – PaulMcG

+0

@PaulMcGuire:根据数学惯例,epsilon和delta都用于小数量。我认为delta实际上是一个更好的选择,因为“epsilon”在浮点运算领域具有特定的含义,这与它在这里的使用方式不同。一个更好的名字将是'comparisonThreshold',然而=) –

+0

@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无关。这只是计算机硬件的工作方式:)