Python中循环遍历一个范围X步骤

3

我有一个圆的半径和方程式y = int(math.sqrt(pow(radius, 2)-pow(i,2)))(勾股定理)。我想要在一个特定范围内进行迭代,步长是16的倍数。以下是一个示例,以说明我的期望输出:

radius = 4
# Desired output: -4, -3.5, -3, -2.5, -2, -1.5, -1, -0.5, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4
# Actually output: -4, -3, -2, 1, 1, 2, 3, 4

我找到了一种使用列表推导式的解决方法。通过将值除以2,我能够实现所需的步长。以下是适用于半径为4的代码:

from itertools import chain

radius = 4
result = [x/2 for x in chain(range(-2*radius, 0), range(1, 2*radius+1))]
print("Length: ", len(result))
print("Values: ", result)

输出结果为16,符合预期。然而,这种方法并不具有普适性,对于其他半径值(例如radius = 5)会失败。我正在寻找一种解决方案,允许我在特定步数内循环遍历一个范围。我该如何实现?


可能是Python decimal range() step value的重复问题。 - Prune
你可以使用Numpy,它有一个函数可以创建类似于你尝试做的列表。numpy.linspace(-radius, radius, radius * radius) - kbunarjo
圆的方程应该是 sqrt(radius * radius - x * x)(使用平方根而不是 int),假设迭代变量为 x。这将给出圆的上半部分。 - Sci Prog
NumPy的解决方案已经包含在重复的问题中。 - Prune
@SciProg 好的,谢谢。 - Gykonik
4个回答

2

解决方案1.1:

您可以使用linspace函数,然后选择那些不为0的值。这可以通过以下代码中的my_range函数完成:

import numpy as np

def my_range(radius, steps):
    ran = np.linspace(-radius, radius, steps+1)
    return ran[np.nonzero(ran)]

现在,
[i for i in my_range(4, 16)]

产生

[-4.0, -3.5, -3.0, -2.5, -2.0, -1.5, -1.0, -0.5, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0]

解决方案 1.2:

或者,

list(my_range(4, 16))

方案2:

如果你不想定义一个函数,这里有一种简洁的方法来实现相同的效果:

产生相同的列表。


[i for i in np.linspace(-4, 4, 16+1) if i != 0]

谢谢!这个方案可行,但请注意,另一个用户的解决方案(不幸的是他再次删除了帖子...)速度稍快:range_steps = (num * 2) / float(steps) #计算增量值以获取步数(LINEBREAK) return list(np.arange(num * -1, num , range_steps)) - Gykonik
@Niklas,你评论中的代码生成了一个包含0的列表。而且它没有包括我示例中列表的最后一个值。因此,你评论中的代码生成了与你定义的期望结果不同的东西。 - yogabonito
是的,我在同一时间看到了那个问题...我的意思是0的问题很容易解决,因为你可以之后删除它,算法仍然会更快,但最后一个值的问题不太容易解决。 - Gykonik
你关于0的说法是正确的。但是我强烈建议在处理浮点类型步长时使用linspace而不是arange。尝试一下np.arange(0, 1.1, 0.1)np.arange(0.5, 1.1, 0.1),比较它们的最后一个值,惊喜吧!(这个例子改编自这个页面。) - yogabonito
是的,你说得对!但看看@f5r5e5d的解决方案!我认为这个不需要任何东西,而且效果也一样,不是吗?(如果你四舍五入结果几乎相同) - Gykonik
显示剩余2条评论

0
希望您喜欢这个解决方案,__future__ 导入适用于 Python 2.x:
from __future__ import division
r = 4
result = [-a/2 for a in xrange(1, r*2+1)][::-1] + [a/2 for a in xrange(1, r*2+1)]
print result

谢谢!这个解决方案可行,但请记住,与@yogabonito的方法相比,这真的很慢! :) - Gykonik
2
我的意思是真的慢:对于9999次计算,你的需要17秒而yogabonito的只需要0.05秒 :D - Gykonik

0

看起来你想要+/-限制相等的幅度

然后你可以选择在范围内包含端点,如果这使你想要获得n + 1个点

纯Python,无导入:

lim, n = 3, 10

[-lim + i * 2 * lim / (n - 1) for i in range(n)]
Out[27]: 
[-3.0,
 -2.3333333333333335,
 -1.6666666666666667,
 -1.0,
 -0.3333333333333335,
 0.3333333333333335,
 1.0,
 1.666666666666667,
 2.333333333333333,
 3.0]

或者

[-lim + i * 2 * lim / n for i in range( n + 1)]
Out[28]: 
[-3.0,
 -2.4,
 -1.8,
 -1.2,
 -0.6000000000000001,
 0.0,
 0.6000000000000001,
 1.2000000000000002,
 1.7999999999999998,
 2.4000000000000004,
 3.0]

将列表推导式中的方括号改为圆括号,就可以得到一个生成器,可以用来替代range()函数。

-1

range函数接受三个参数:起始值start,终止值stop和步长step(第三个参数是可选的)。range(-4,4,0.5)可以解决你的问题。 因此,假设-x是起始值,x是终止值。

step =  int(x/16);
range(-x, x, step);

range() 需要一个整数步长。 - martineau
OP特别要求使用分数步长的解决方案,而“range”不允许这样做。您的示例提供了一个步长值为0。 - Prune

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接