将0.0转换为0时代码有效,但1.0时失败?

时间:2017-08-27 08:37:13

标签: python floating-point precision

Python,版本3.5

我有以下代码:

def drange(start, stop, step):
    r = start
    while r < stop:
        yield r
        r += step

def my_func():
    whole_nums = [float(num) for num in range(0, 100)]
    for x in drange(0.0, 100.01, 0.01):
        if str(x).split('.')[1] == '0':
            x = str(x).split('.')[0]
        else:
            x = round(x, 2)
        print(str(x))
        time.sleep(0.2)

drange函数循环给定的数字,给定的增量并产生数字。问题是我想要0,1,2,3等,但它会产生0.0,1.0等等。

我认为既然我知道那些错误数字的格式(介于0.01之间的所有其他数字,一直到我想要的99.99)我可以这样做:

str(theNumber).split('.')[1]

(如my_func所示),如果输出为'0',那么我知道我有一个0.0,1.0等,可以用str(theNumber).split('.')[0]获取我想要的输出,当然将它转换为int或其他。

但是!当我执行my_func时,.split()解决方案仅适用于0.0,当它达到1.0时,它只是跳过if语句并进入else,打印出1.0而不是1。

代码应该运行良好而不导入任何东西,所以随意给它一个旋转。

更新

好吧,看来我的方法存在根本缺陷(请参阅@danils答案)所以现在我的问题是:如何生成0到100之间的数字,增量为0.01,同时确保整数是完整的。所以

0, 0.01, ..., 1, 1.01, 1.1, 1.02, ... 99.5, 99.51, ..., 100

3 个答案:

答案 0 :(得分:2)

你永远不应该依赖浮点整数的字符串表示,因为它们很少有精确的表示(近似导致精确的不准确性,这会导致扳手在工作中)。

您不需要str(x)print,因为print会自动为您执行此操作。

此外,在步骤中生成下一个值时,您的drange函数似乎会引入浮点不准确性。您可以使用np.arange作为范围,它支持小数步骤:

import numpy as np
out = np.arange(0.0, 100.01, 0.01)
print(out)

array([  0.00000000e+00,   1.00000000e-02,   2.00000000e-02, ...,
         9.99800000e+01,   9.99900000e+01,   1.00000000e+02])

注意:如果您没有numpy,可以使用pip install numpy进行安装。

最后,您可以使用float.is_integer来检查浮点数是否为整数。

for x in np.arange(0.0, 100.01, 0.01):
    if x.is_integer():
        x = int(x)
    else:
        x = round(x, 2)

    print(x)

这会给你:

0
0.01
0.02
0.03
0.04
0.05
0.06
0.07
0.08
0.09
0.1
...

答案 1 :(得分:0)

这是因为浮点运算。它并不完全是1.0你得到的,更像是1.0000000000000007。所以str(x).split('.')[1] == '0000000000000007'

> import numpy as np
> np.arange(0.0, 100.0, 0.1)
array([   0. ,    0.1,    0.2, ...,   99.8,   99.9,  100. ])

答案 2 :(得分:0)

对于不涉及numpy的版本:

import time

def drange(start, stop, step):
    r = start
    while r < stop:
        yield r
        r += step

def my_func():
    whole_nums = [float(num) for num in range(0, 100)]
    for x in drange(0.0, 100.01, 0.01):
        x = float(int(x * 100))/100
        if x.is_integer():
            print(int(x))
        else:
            print (x)
        time.sleep(0.01)

if __name__ == "__main__":
    my_func()

不可否认,截断功能很俗气。