本问题已经有最佳答案,请猛点这里访问。
文件基本上说,range必须与此实现完全一致(对于积极的step而言):
def range(start, stop, step):
x = start
while True:
if x >= stop: return
yield x
x += step
它还说它的参数必须是整数。为什么?如果步骤是浮点,那么这个定义是否也完全有效?
在我的例子中,我特别需要一个接受float类型作为其step参数的range函数。在python中是否有或者我需要实现我自己的?
更具体的一点是:我如何以一种好的方式将这个C代码直接转换为python(即,不仅仅是通过while循环手动地进行转换):
for(float x = 0; x < 10; x += 0.5f) { /* ... */ }
号
循环中不能有return和yield关键字,请使用break。
@蒂姆:当然可以。
看起来你可以!我认为那是不可能的。我敢肯定,当我尝试类似的方法时,错误已经出现了。
以您发布的代码为例,将其重命名为float_rangedone。
@蒂姆:return变为raise StopIteration;return变为SyntaxError: 'return' with argument inside generator——甚至是return None。
实际上,range()返回一个列表。OP所描述的实际上是xrange(),它一次返回一个元素。
你可以使用numpy.arange。
编辑:单据首选numpy.linspace。谢谢@drougans for notcing=)
第一段说明:当使用非整数步骤(如0.1)时,结果通常不一致。在这些情况下,最好使用linspace。
注意,linspace有不同的接口。
甚至没有麻木的感觉。我做了一个Xfrange函数,没有浮点精度问题。查看;)stackoverflow.com/questions/477486/&hellip;
一种解释可能是浮点舍入问题。例如,如果你可以打电话
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
。
是的,当然(这样做很自然)。浮点数总是这样。当然,如果range支持float,那么它的行为是完全合法的。所以我不明白为什么不应该这样。
是的,你说得对。我能想到的最好的办法就是"它不精确"。"可能是因为一些常见的实现细节而有必要这样做?"
@阿尔伯特:通常没什么必要去想为什么会做出这样的决定,他们只是。在这种情况下,有限的用例将被潜在的恶意bug所超越。
你在累积舍入误差。请用这个来代替:`i=0;r=start while r为什么这件事被否决了这么多?请考虑@ceestimmerman的评论,并将其纳入您的答案中,以获得不会累积舍入错误的解决方案。
@乔希,我显然错过了塞斯的评论。当然,你是绝对正确的,我的版本会像疯了一样累积舍入误差。事实上,我有点不安,因为这显然是错误的!但现在-终于-解决了。谢谢你提醒我。
因step为阴性而损坏,请按这样修复您的while状态:while (start + i * step) * (-1 if step < 0 else 1) < stop:
为了能够在范围表达式中使用十进制数,一种很酷的方法是:[X*0.1代表范围内的X(0,10)]
如果你的"range"有很多数字,而你的"step"0.1更小,比如说.00000001,那么这就行不通了,脚本只会挂在大多数计算机上。我们需要一些东西来模拟xrange的功能,比如我们需要一个iterable/generator,而不是列出comprehension.fxrange范围,在这种情况下效果更好。
非常简单的列表理解解决方案,谢谢!
@EKTA使用()而不是[]将其转化为发电机。
我只需要一些简单的东西,这是我从本地range所期望的——我对这个解决方案很满意
浮点的问题是,由于不准确,您可能无法获得与预期数量相同的项目。这是一个真正的问题,如果你在玩多项式,精确的项目数量是非常重要的。
你真正想要的是一个算术级数;下面的代码对于int、float和complex来说非常有用……还有字符串和列表…
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)
。
更正:这是一个竞争性的运行总计小工具:
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的步长正好是0x1.1999999999AP+0。OP发布的代码并不是一个完美的解决方案,因为重复添加不精确的值会使错误累积。最好在迭代过程中跟踪循环数,并将步长乘以循环数,就像其他答案已经显示的那样。
@我指的是一般情况,不是那些数字。
那么我们对"确定"的定义就不同了。即使使用浮点数,计算机也不会给出"不确定"或"随机"的结果。结果总是决定性的。无论输入的是什么,只要给定一个有限的浮点数,你总是能够确定地说,在用给定的精度加上x次之后,它们的结果是什么。
@我根据你的反馈做了一些修改,谢谢。
这现在很有道理。谢谢!
这里有一个非常好的案例:
[ (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]
这就是我要用的:
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]
号
希望有帮助。
这并不能回答这个问题。要评论或要求作者澄清,请在他们的帖子下面留下评论-你可以随时对自己的帖子发表评论,一旦你有足够的声誉,你就可以对任何帖子发表评论。
@请注意,如果他使用0.5而不是0.1,则不会出现意外行为。
可能是因为你不能拥有一个不可数的一部分。另外,floats是不精确的。
浮点数非常精确。他们不擅长的是表示某些值,这些值以10为基数具有有限表示。例如,以10为基数的0.1将成为内存中的0x1.999999999AP-4(使用精确的十六进制浮点表示法),而不是精确的十进制0.1。有了这个参数,你也可以说十进制数字是不精确的,因为有些值没有有限的表示…