Python 带浮动类型步长的范围

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4189766/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 14:42:35  来源:igfitidea点击:

Range with step of type float

pythonrange

提问by Albert

The documentationbasically says that rangemust behave exactly as this implementation (for positive step):

文档基本上说range必须完全按照这个实现(对于 positive step):

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

It also says that its arguments must be integers. Why is that? Isn't that definition also perfectly valid if step is a float?

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

In my case, I am esp. needing a rangefunction which accepts a float type as its stepargument. Is there any in Python or do I need to implement my own?

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



More specific: How would I translate this C code directly to Python in a nice way (i.e. not just doing it via a while-loop manually):

更具体地说:我将如何以一种很好的方式将此 C 代码直接转换为 Python(即不仅仅是通过while-loop 手动执行):

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

采纳答案by Katriel

You could use numpy.arange.

你可以使用numpy.arange.

EDIT: The docs prefer numpy.linspace. Thanks @Droogans for noticing =)

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

回答by Tim McNamara

Probably because you can't have part of an iterable. Also, floatsare imprecise.

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

回答by Mark Ransom

When you add floating point numbers together, there's often a little bit of error. Would a range(0.0, 2.2, 1.1)return [0.0, 1.1]or [0.0, 1.1, 2.199999999]? There's no way to be certain without rigorous analysis.

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

The code you posted is an OK work-around if you really need this. Just be aware of the possible shortcomings.

如果你真的需要这个,你发布的代码是一个不错的解决方法。请注意可能存在的缺点。

回答by Zarkonnen

One explanation might be floating point rounding issues. For example, if you could call

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

range(0, 0.4, 0.1)

you might expect an output of

你可能期望输出

[0, 0.1, 0.2, 0.3]

but you in fact get something like

但你实际上得到了类似的东西

[0, 0.1, 0.2000000001, 0.3000000001]

due to rounding issues. And since range is often used to generate indices of some sort, it's integers only.

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

Still, if you want a range generator for floats, you can just roll your own.

尽管如此,如果你想要一个用于浮动的范围生成器,你可以自己滚动。

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

回答by John Machin

The problem with floating point is that you may not get the same number of items as you expected, due to inaccuracy. This can be a real problem if you are playing with polynomials where the exact number of items is quite important.

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

What you really want is an arithmetic progression; the following code will work quite happily for int, floatand complex... and strings, and lists ...

你真正想要的是一个等差数列;下面的代码很适合用于int, floatand complex... 和字符串,以及列表 ...

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

Note that this code stands a better chance of your last value being within a bull's roar of the expected value than any alternative which maintains a running total.

请注意,与保持运行总数的任何替代方案相比,此代码更有可能使您的最后一个值处于预期值的牛市咆哮之内。

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

Correction: here's a 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
>>>

回答by mariana soffer

In order to be able to use decimal numbers in a range expression a cool way for doing it is the following: [x * 0.1 for x in range(0, 10)]

为了能够在范围表达式中使用十进制数,一个很酷的方法是:[x * 0.1 for x in range(0, 10)]

回答by ntg

Here is a special case that might be good enough:

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

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

In your case this would be:

在您的情况下,这将是:

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

and so:

所以:

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

回答by Andrey

This is what I would use:

这就是我会使用的:

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

rather than:

而不是:

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]

hope it helps.

希望能帮助到你。