Python-如何生成具有多个范围的随机整数?

时间:2015-11-16 07:35:16

标签: python random integer

我在从(a,b)的不同集合生成X量的随机整数时遇到了困惑。例如,我想生成来自(1,5),(9,15)和(21,27)的5个随机整数。我的代码生成5个随机整数,但只有21到27之间,而不是其他两个。理想情况下,我希望看到1,4,13,22,25而不是21,21,25,24,27。

我的代码:

from random import randint
n = 0
while n < 5:
    n += 1
    for i in (randint(1,5),randint(9,15),randint(21,27)):
        x = i
    print i

7 个答案:

答案 0 :(得分:8)

不理想

from random import randint, choice

for _ in range(5):
    print(choice([randint(1,5),randint(9,15),randint(21,27)]))

正如Blender所说 - 更清晰的版本

from random import randint, choice

for _ in range(5):
    r = choice([(1,5),(9,15),(21,27)])
    print(randint(*r))

答案 1 :(得分:2)

你好!

这是一个有趣的问题;当你意识到要实现真正的随机性时,选择一个特定范围的概率必须用该范围的长度来衡量。

等长范围:

如果三个范围具有相等的长度,例如范围(0,10),范围(20,30)和范围(40,50);然后,要选择一个随机数,我们可以执行以下操作:

  1. 随机选择一个范围。
  2. 从该范围中选择一个随机数。
  3. 不等长度的范围:

    现在,考虑三个不等大小的范​​围,例如范围(0,2),范围(4,6)和范围(10,100);

    第三个范围比前两个范围大得多。如果我们采用与处理同样长距离相同的策略,我们将偏向于从前两个范围中选择数字。

    为了从三个不等长的范围中选择真正的随机数,有两种策略。

    策略1:使用概率

    挑选范围的概率应该是选择数字的概率保持不变。我们可以通过权衡缩小范围的可能性来实现这一目标。

    然而,不是计算概率权重;这是一个更好的解决方案。见策略2.

    策略2:合并范围

    我们可以简单地将三个范围合并为一个单一范围。然后,从合并范围中随机选择一个数字。很简单:

    import random;
    def randomPicker(howMany, *ranges):
        mergedRange = reduce(lambda a, b: a + b, ranges);
        ans = [];
        for i in range(howMany):
            ans.append(random.choice(mergedRange));
        return ans;
    

    让我们看看它的实际效果:

    >>> randomPicker(5, range(0, 10), range(15, 20), range(40, 60));
    [47, 50, 4, 50, 16]
    >>> randomPicker(5, range(0, 10), range(70, 90), range(40, 60));
    [0, 9, 55, 46, 44]
    >>> randomPicker(5, range(0, 10), range(40, 60));
    [50, 43, 7, 42, 4]
    >>> 
    

    randomPicker的另一个好处是它可以处理任意数量的范围。

    希望这会有所帮助。

答案 2 :(得分:1)

<form  method="post" enctype="multipart/form-data" ng-controller="commentCtrl" name="form">
        <a href="" type="file" class="custom-height"><img src="source/assets/images/icons/icofileattached.png" class="attachmentpng-height"  ngf-select="uploadFiles($file)" ng-model="files"/></a>
        <md-button type="submit" class="md-raised custom-submit-button" ng-click="MakeComments()"> SUBMIT </md-button>
        </form>

这个foor循环将从提供的第一个范围生成一个随机数,另一个用于第二个范围,最后一个用于最后一个范围,并在输出上打印每一个。 您的打印不在foor循环中,只打印最后一个范围内的最后一个随机数。

答案 3 :(得分:0)

表示非重复数字:

from random import randint, choice

randoms = []
counter = 0    
while True:
   new_random = (choice([randint(1,5),randint(9,15),randint(21,27)]))
   if new_random not in randoms:
      randoms.append(new_random)
      counter += 1
   if counter == 5 :
      break
print randoms

答案 4 :(得分:0)

这里有一些有趣的答案,但我认为这个问题可以通过少量代码解决,即使它的可读性稍差。

这里的基本思想是你有一个固定数量的选择,所以你基本上可以有一个范围来完成这项工作,然后将结果绘制到你想要的范围。或者,如果您想以另一种方式考虑它,请创建一个函数f(x) -> y,归结为同样的事情。

from random import randint

for i in xrange(5):
    n = randint(1,19)
    if n > 12:
        print(n + 8)
    elif n > 5:
        print(n + 3)
    else:
        print(n)

或者,有一个功能:

from random import randint

def plot_to_ranges(n):
    if n > 12:
        return n + 8
    elif n > 5:
        return n + 3
    else:
        return n

for i in xrange(5):
    n = randint(1,19)
    print(plot_to_ranges(n))

如果您使用的是Python 3.x,则应将xrange更改为range

答案 5 :(得分:0)

import itertools, random
nums = list(itertools.chain(
            range(1,5),
            range(9,15),
            range(21,27)))
random.choices(nums, k=5)

答案 6 :(得分:0)

Sumukh Barve 回答的补充:

策略 3:在不串联范围的情况下选择范围的成员

此方法对指定范围的长度求和。然后它产生一个在该范围内的随机整数。然后它根据它相对于范围的位置添加到该整数。

示例: 如果范围是 (1,3) 和 (5,9),则范围包括在内。将所有范围的长度相加得到 3+4=7。然后我们创建一个介于 1 到 7(或 0 到 6)之间的随机整数。假设我们得到 2,我们从第一个范围中选择第二个项目。如果我们得到 5,我们从第二个范围中选择第二个项目。

def randint_within_ranges(ranges):
    """ranges is a list of tuples, where each tuple is a range. E.g. [(0, 2), (4, 6), (10, 100)]. 
    Ranges must be non-overlapping. 
    Ranges are inclusive (e.g. can return 4 or 6).
    Returns a random int anywhere in any of those ranges. 
    (In this example, high probability will be from (10,100) range.)
    """
    #in case ranges aren't ordered, sort them now. Lowest first, e.g. [(0, 2), (4, 6), (10, 100)]
    ranges = sorted(ranges, key=min)
    #print('ranges',ranges)
    total_range_size = sum([abs(range_[1]-range_[0])+1 for range_ in ranges])
    #print('total_range_size',total_range_size)
    lowest_range_start = min([min(range_) for range_ in ranges])
    #print('lowest_range_start',lowest_range_start)
    randint = random.randint(0, total_range_size-1) 
    #print('randint',randint)
    randint += lowest_range_start
    #print('randint',randint)

    #add the gaps
    for i in range(len(ranges)-1):
        if randint > max(ranges[i]):
            randint += (min(ranges[i+1])-max(ranges[i])-1)#gaps[i]
        
    return randint

print(  randint_within_ranges([ (4, 6), (-300, -290), (285,289), (10, 15), (48,53), (85,91)])  )

您可以使用以下方法测试这仅返回范围内的数字。范围包括两个边界。

randints = set()
for i in range(1000): 
    randints.add(randint_within_ranges([ (4, 6), (-300, -290), (285,289), (10, 15), (48,53), (85,91)]))
print(len(randints), sorted(list(randints)))