具有float类型的步长的范围

时间:2010-11-15 23:09:28

标签: python range

The documentation基本上说range必须与此实施完全相同(对于正step}:

def range(start, stop, step):
  x = start
  while True:
    if x >= stop: return
    yield x
    x += step

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

就我而言,我是特别的。需要一个range函数,它接受一个float类型作为其step参数。在Python中有没有,或者我需要实现自己的?


更具体:我如何以一种很好的方式将这个C代码直接翻译成Python(即不只是通过while - 手动循环):

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

8 个答案:

答案 0 :(得分:51)

您可以使用numpy.arange

编辑:文档更喜欢numpy.linspace感谢@Droogans注意=)

答案 1 :(得分:35)

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

range(0, 0.4, 0.1)

您可能希望输出

[0, 0.1, 0.2, 0.3]

但事实上你得到像

这样的东西
[0, 0.1, 0.2000000001, 0.3000000001]

由于四舍五入问题。因为范围通常用于生成某种索引,所以它只是整数。

但是,如果你想要一个用于浮动的范围生成器,你可以自己动手。

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

答案 2 :(得分:13)

为了能够在范围表达式中使用十进制数字,执行此操作的一种很酷的方法如下: [x * 0.1表示x在范围内(0,10)]

答案 3 :(得分:6)

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

你真正想要的是算术级数;以下代码非常适合intfloatcomplex ...以及字符串和列表......

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

请注意,此代码更有可能使您的最后一个值在预期值的公牛咆哮范围内,而不是任何维持运行总计的替代值。

>>> 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)

更正:这是competetive running-total gadget

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

答案 4 :(得分:5)

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

如果您真的需要,您发布的代码是一个好的解决方法。请注意可能的缺点。

答案 5 :(得分:3)

这是一个可能足够好的特殊情况:

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

在你的情况下,这将是:

#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'

所以:

>>> [ .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]

答案 6 :(得分:1)

这就是我要用的:

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

而不是:

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]
希望它有所帮助。

答案 7 :(得分:-1)

可能是因为你不能拥有可迭代的一部分。此外,floats还不精确。