Python 在一定范围内生成均匀分布的倍数/样本

Python 在一定范围内生成均匀分布的倍数/样本,python,Python,问题的具体实例 我的整数范围是1-100。我希望在此范围内生成n个总数,这些总数尽可能均匀分布,并包括第一个和最后一个值 示例 start = 1, end = 100, n = 5 Output: [1, 25, 50, 75, 100] start = 1, end = 100, n = 4 Output: [1, 33, 66, 100] start = 1, end = 100, n = 2 Output: [1, 100] 我目前拥有的 我其实有一个工作方法,但

问题的具体实例
我的整数范围是1-100。我希望在此范围内生成n个总数,这些总数尽可能均匀分布,并包括第一个和最后一个值

示例

start = 1, end = 100, n = 5   
Output: [1, 25, 50, 75, 100]

start = 1, end = 100, n = 4   
Output: [1, 33, 66, 100]

start = 1, end = 100, n = 2   
Output: [1, 100]
我目前拥有的
我其实有一个工作方法,但我一直觉得我想得太多了,错过了一些更简单的东西?这是最有效的方法还是可以改进

def步骤(开始、结束、n):
n=最小值(结束,最大值(n,2)-1)
mult=结束/浮动(n)
产量起点
对于X范围内的刻度(1,n+1):
val=int(多重*比例)
如果val!=开始:
屈服值
注意,我要确保此函数始终至少返回范围的下限值和上限值。因此,我强制
n>=2

仅作为搜索参考,我使用它对渲染序列中的图像帧进行采样,通常需要第一帧、中间帧和最后一帧。但我希望能够更好地进行缩放,以处理非常长的图像序列并获得更好的覆盖率

已解决:来自所选答案

我最终使用了@vartec答案的这个稍加修改的版本,作为一个生成器,并为安全设置了
n
值的上限:

def steps(start,end,n):
    n = min(end, max(n, 2))
    step = (end-start)/float(n-1)
    return (int(round(start+x*step)) for x in xrange(n))
使用有什么问题?以下是您如何使用它

>>> def steps(start,end,n):
    return [start]+range(start-1,end,end/(n-1))[1:]+[end]

>>> steps(1,100,5)
[1, 25, 50, 75, 100]
>>> steps(1,100,2)
[1, 100]
>>> 
可以缩短为

>>> from itertools import islice, count
>>> def steps(start,end,n):
        yield start
        begin = start if start>1 else 0
        c = islice(count(begin,(end-begin)/(n-1)),1,None)
        for _ in range(n-2):
            yield next(c)
        yield end

使用
range
的问题是步长必须是整数,因此会出现舍入问题,例如
步长(1100,4)=[1,33,66,100]
。如果您想要整数输出,但想要尽可能均匀的步长,请使用浮点作为步长

>>> def steps(start,end,n):
...    step = (end-start)/float(n-1)
...    return [int(round(start+i*step)) for i in range(n)]

>>> steps(1,100,5)
>>> [1, 26, 51, 75, 100]
>>> steps(1,100,4)
>>> [1, 34, 67, 100]
>>> steps(1,100,2)
>>> [1, 100]
>>>

额外的依赖性,可能是过度的,但很短,经过测试,应该给出正确的结果:


您需要适当的舍入:

def steps(start,end,n):
    if n<2:
        raise Exception("behaviour not defined for n<2")
    step = (end-start)/float(n-1)
    return [int(round(start+x*step)) for x in range(n)]
def步骤(开始、结束、n):


如果我和你有完全相同的代码。。。比赛条件…:D:-)你本来可以把它贴出来的。至少人们会根据时间的不同理解啊,最好不要。。。这会引起混乱+1 btwI非常喜欢它的发展方向,但与我的处理方式相比,当
n==4
时,它有一个问题。与@jamylakSorry的答案相同,它只是在数值上不稳定。您有舍入错误问题:
步骤(1100,15)
->
[1,7,14,21,28,35,42,49,56,63,70,77,84,91,98,100]
到目前为止,您和@Abhijit都有很好的建议,但他们都对
n==4有问题。他们返回5个分布不均匀的结果。感谢更新版本!我投了赞成票,但有些人提出了一个较短的版本,也解决了我的小舍入疏忽。您的代码不处理
列表(步骤(50100,3))
[1,33,66100]
甚至不可能,它应该是
[1,33,67100]
,毕竟66.66(6)应该舍入,没有向下。例如2你的数字间隔不均匀(见我的答案),或者我遗漏了什么吗?@bmu:你没有遗漏任何东西。我忘了用
round
来拉近距离。@vartec:你说得对,我忘了用
round
:-)啊,真酷!在这种情况下,我想限制我的依赖性,但我投票赞成,并将记住这是可用的。谢谢@瓦特克:在你发表评论之前,他解决了舍入问题吗?上面说你在他一定把它修好后发表了评论,现在你们都有了相同的答案。因为我想接受它,所以我试图找出谁是第一个拥有它的人。@jdi:这很容易检查,只需将鼠标悬停在“N小时前”上即可。他的编辑时间是在我回答后10分钟。@vartec:啊,我把它们比较错了。我在看他的编辑和你的评论的时间戳(不是你的答案和他的编辑)。@vartec:我回来编辑时错过了你的答案。你指的是什么33.33?@iainlist:NVM,我的错,我是从0开始数的。不管怎样,没关系,你得到了我的支持,因为你的答案也是正确的。谢谢你简化了这个。我忽略了
,很可能是因为这个特定的应用程序不太敏感,比如说66对67,所以它没有向我发出信号。@NathanRossPowell:there
>>> numpy.linspace(1, 100, 4).astype(int).tolist()
[1, 34, 67, 100]
def steps(start,end,n):
    if n<2:
        raise Exception("behaviour not defined for n<2")
    step = (end-start)/float(n-1)
    return [int(round(start+x*step)) for x in range(n)]