关于python:类型为float的步骤范围

Range with step of type float

本问题已经有最佳答案,请猛点这里访问。

文件基本上说,range必须与此实现完全一致(对于积极的step而言):

1
2
3
4
5
6
def range(start, stop, step):
  x = start
  while True:
    if x >= stop: return
    yield x
    x += step

它还说它的参数必须是整数。为什么?如果步骤是浮点,那么这个定义是否也完全有效?

在我的例子中,我特别需要一个接受float类型作为其step参数的range函数。在python中是否有或者我需要实现我自己的?

更具体的一点是:我如何以一种好的方式将这个C代码直接转换为python(即,不仅仅是通过while循环手动地进行转换):

1
for(float x = 0; x < 10; x += 0.5f) { /* ... */ }


你可以使用numpy.arange

编辑:单据首选numpy.linspace谢谢@drougans for notcing=)


一种解释可能是浮点舍入问题。例如,如果你可以打电话

1
range(0, 0.4, 0.1)

您可能期望输出

1
[0, 0.1, 0.2, 0.3]

但事实上你得到了

1
[0, 0.1, 0.2000000001, 0.3000000001]

由于舍入问题。由于范围经常被用来生成某种类型的索引,所以它只是整数。

不过,如果你想要一个浮动范围生成器,你可以自己滚动。

1
2
3
4
5
def xfrange(start, stop, step):
    i = 0
    while start + i * step < stop:
        yield start + i * step
        i += 1


为了能够在范围表达式中使用十进制数,一种很酷的方法是:[X*0.1代表范围内的X(0,10)]


浮点的问题是,由于不准确,您可能无法获得与预期数量相同的项目。这是一个真正的问题,如果你在玩多项式,精确的项目数量是非常重要的。

你真正想要的是一个算术级数;下面的代码对于intfloatcomplex来说非常有用……还有字符串和列表…

1
2
3
def arithmetic_progression(start, step, length):
    for i in xrange(length):
        yield start + i * step

注意,这段代码比任何其他保持运行总数的代码都更有可能使您的最后一个值处于预期值的牛市之内。

1
2
3
4
>>> 10000 * 0.0001, sum(0.0001 for i in xrange(10000))
(1.0, 0.9999999999999062)
>>> 10000 * (1/3.), sum(1/3. for i in xrange(10000))
(3333.333333333333, 3333.3333333337314)

更正:这是一个竞争性的运行总计小工具:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
def kahan_range(start, stop, step):
    assert step > 0.0
    total = start
    compo = 0.0
    while total < stop:
        yield total
        y = step - compo
        temp = total + y
        compo = (temp - total) - y
        total = temp

>>> list(kahan_range(0, 1, 0.0001))[-1]
0.9999
>>> list(kahan_range(0, 3333.3334, 1/3.))[-1]
3333.333333333333
>>>


当你把浮点数加在一起时,通常会有一点错误。range(0.0, 2.2, 1.1)会返回[0.0, 1.1]还是[0.0, 1.1, 2.199999999]?没有严格的分析是无法确定的。

如果你真的需要的话,你发布的代码是一个很好的解决方法。只需意识到可能存在的缺点。


这里有一个非常好的案例:

1
 [ (1.0/divStep)*x for x in range(start*divStep, stop*divStep)]

在您的情况下,这将是:

1
2
3
4
#for(float x = 0; x < 10; x += 0.5f) { /* ... */ } ==>
start = 0
stop  = 10
divstep = 1/.5 = 2 #This needs to be int, thats why I said 'special case'

所以:

1
2
>>> [ .5*x for x in range(0*2, 10*2)]
[0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5]


这就是我要用的:

1
numbers = [float(x)/10 for x in range(10)]

而不是:

1
2
3
numbers = [x*0.1 for x in range(10)]
that would return :
[0.0, 0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6000000000000001, 0.7000000000000001, 0.8, 0.9]

希望有帮助。


可能是因为你不能拥有一个不可数的一部分。另外,floats是不精确的。