12

我只是想知道如何让 python 生成除特定数字以外的随机数?例如,我希望它生成除 3 之外的从 1 到 5 的任何数字,因此输出1, 2, 4, 53不会计入列表中。我能做些什么来实现这一目标?

一个例子是这样的:一个游戏中
五个计算机化的玩家(玩家 0 到 4)。
玩家 1 随机选择其他玩家(除了自己),玩家 2 到 4 也会做同样的事情。

所以输出将是这样的:

Player 1, who do you want to play with?
Player 1 chooses Player 2
4

6 回答 6

18

在列表中使用random.choice,但首先从列表中删除该特定数字:

>>> import random
>>> n = 3
>>> end  = 5
>>> r = range(1,n) + range(n+1, end)
>>> r
[1, 2, 4]
>>> random.choice(r)
2
>>> random.choice(r)
4

或者定义一个函数:

def func(n, end, start = 1):
    return range(start, n) + range(n+1, end)
... 
>>> r = func(3, 5)
>>> r
[1, 2, 4]
>>> random.choice(r)
2

更新:

这将返回列表中除特定数字之外的所有数字:

>>> r = range(5)
for player in r:
    others = range(0, player) + range(player+1, 5)
    print player,'-->', others
...     
0 --> [1, 2, 3, 4]
1 --> [0, 2, 3, 4]
2 --> [0, 1, 3, 4]
3 --> [0, 1, 2, 4]
4 --> [0, 1, 2, 3]
于 2013-07-28T10:24:01.103 回答
5

听起来好像您想生成一组随机数字,然后从这些数字中一个接一个地进行选择。换句话说,没有重复的随机序列。

生成所有这些数字,随机播放,然后使用.pop()一次选择一个并将其从一组可能性中删除:

import random

numbers = range(5)  # list(range(5)) in Python 3
random.shuffle(numbers)

a_random_number = numbers.pop()
another_random_number = numbers.pop()

list.pop()从随机打乱的数字列表中删除最后一个值。

甚至只是洗牌然后循环列表就足够了:

players = range(5)
random.shuffle(players)

for player in players:
    # random ordering of players

您可以将随机数序列生成捆绑为函数中的迭代器:

import random

def random_number_sequence(n):
    numbers = range(n)  # list(range(n)) in Python 3
    random.shuffle(numbers)
    return iter(numbers)

random_sequence = random_number_sequence(5)
a_random_number = next(numbers)
another_random_number = next(numbers)

您可以调用next()迭代器,它将从序列中生成另一个随机数,直到序列用尽(此时StopIteration返回)。

于 2013-07-28T10:49:48.970 回答
4

而其他答案是正确的。使用中间列表是低效的。


替代解决方案:您可以执行此操作的另一种方法是从大小为 n-1 的数字范围中随机选择。然后将 +1 添加到大于或等于 >= 您要跳过的数字的任何结果。

以下函数random_choice_except实现了与 相同的 API np.random.choice,因此调整size允许有效地生成多个随机值:


import numpy as np

def random_choice_except(a: int, excluding: int, size=None, replace=True):
    # generate random values in the range [0, a)
    choices = np.random.choice(a-1, size, replace=replace)
    # shift values to avoid the excluded number
    return choices + (choices >= excluding)

random_choice_except(3, 1)
# >>> 0  <or>  2  
random_choice_except(3, 1)
# >>> [0 2 0 0 0 2 2 0 0 2]

更改的行为np.random.choice取决于是否将整数、列表或数组作为参数传递。为了防止不需要的行为,我们可能希望在函数顶部添加以下断言:assert isinstance(a, int)

于 2020-09-22T18:00:50.980 回答
1

在这种情况下,random.choice可以正常工作,但您也可以使用一个明显的简单数学变换。如果玩家编号为 0 到 5(含),并且您是玩家 X,那么:

number = random.choice(0, 4) # first, pick a number: 0, 1, 2, 3, or 4
if number >= X:              # then, if it's me or higher...
    number += 1              # move forward one player

请注意,无论您是哪个玩家编号,这都有效。如果你是#5,这会选择一个介于 0 和 4 之间的数字,这不是你(因为你是#5)。如果你是#0,这会选择一个介于 0 和 4 之间的数字,即 >= 你(因为你是 #0)所以你加 1 给出一个介于 1 和 5 之间的数字。如果你是 #3,这会选择一个介于0 和 4,如果是 3 或 4,则分别将其提高 1 至 4 或 5。

编辑添加:这将不允许您进行“公平”交替(每个人都可以在有人再次出发之前轮流)。如果你想要这样,生成一个列表,使用random.shuffle它以随机顺序放置,然后从列表中选择(有.pop()或类似的)直到它为空是要走的路。然后,您可以重新填写并重新洗牌以获得新的(但不同的)“公平”订单。

(请注意,这就是为什么在讨论“如何到达那里”之前弄清楚你想要什么很重要的原因。)

于 2013-07-28T11:24:10.600 回答
0

这个想法是。从 LIST(A) 中选择随机数 每次从 LIST(A) 中选择随机数时,LIST(A) 都会变小。所以你不能重复。如果 Python pics '2' 第一次。它不能第二次这样做,因为 '2' 不在 LIST(A) 中......

import random 
random_numbers =  [1,2,3,4,5] 
X = []
while True:
    one = random.choice(random_numbers))
    # print(one)
    if str(one) not in X:
        X.append(str(one))
        break

    if '2' in X:
        print("Last number was 2 with out repeating!")
        print("You did it u pick random numbers one by one with out repeating")
    random_numbers.remove(one)

print(X)
于 2020-04-06T21:08:33.570 回答
0

我建议使用递归函数。

import random

def randint_exc(start, end, exception):
    res = random.randint(start, end)
    if res != exception:
        return res
    else:
        return randint_exc(start, end, exception)

test = randint_exc(1, 4, 1)
print(test)
# results will be 2 or 3 or 4

对于可变数量的异常,您可以使用*args参数。

def randint_exc(start, end, *exception):
    res = random.randint(start, end)
    if res not in exception:
        return res
    else:
        return randint_exc(start, end, *exception)

test1 = randint_exc(1, 4, 1)
print(test1)
# results will be 2 or 3 or 4
test2 = randint_exc(1, 4, 1, 2)
print(test2)
# results will be 3 or 4

或者您可以使用list更易于阅读。

def randint_exc(start, end, exception_list):
    res = random.randint(start, end)
    if res not in exception_list:
        return res
    else:
        return randint_exc(start, end, exception_list)

test1 = randint_exc(1, 4, [1])
print(test1)
# results will be 2 or 3 or 4
test2 = randint_exc(1, 4, [1, 2])
print(test2)
# results will be 3 or 4
于 2022-03-06T01:49:03.650 回答