如果一个数字与另一个数字过于相似,如何设置循环,使其生成新的随机数字?

时间:2018-09-14 01:51:15

标签: python

我正在尝试使用random模块生成(伪)随机数。我需要生成的数字在范围上不要太接近。例如,如果生成数字n,则另一个数字x不能为n + -5。

from random import randint

i = 10

j_list = []
k_list = []

while i != 0:

    j = randint(-10, 10)
    k = randint(-15, 15)

    j_list.append(j)
    k_list.append(k)

    i -= 1

print("J list is: {} and K list is {}".format(j_list, k_list))

例如,当我上次运行它时,得到以下输出:

J list is: [-4, 5, 2, -3, 7, -4, 3, -1, -1, -6] and K list is [10, 3, -7, -1, -5, -11, 3, 8, 1, -7]

如您所见,j_list的第1个元素和第3个元素(即j_list [1:3])在+5之内。这不是我想要的;我希望列表中的每个元素都产生超出特定范围的值。

有什么办法吗?

3 个答案:

答案 0 :(得分:2)

首先,在这里使用for循环比使用while循环更好:

# One line and you know the loop range immediately
for i in range(10):
    print(i)

# Three lines and takes the reader two seconds to comprehend
i = 10
while i != 0:
    i -= 1
    print(i)

现在回答您的问题,您可以使用random.choice排除范围(j-5,j + 5):

from random import randint, choice

j_list = []
k_list = []

for i in range(10):

    j = randint(-10, 10)
    k = choice([n for n in range(-15, 15) if n not in range(j - 5, j + 6)])

    j_list.append(j)
    k_list.append(k)

print("J list is: {} and K list is {}".format(j_list, k_list))

如果只想使用randint,另一种方法是使用while循环保持重新滚动值k,直到它不落在j + -5范围内:

from random import randint

j_list = []
k_list = []

for i in range(10):

    j = randint(-10, 10)
    k = randint(-15, 15)

    while abs(j - k) <= 5:

        k = randint(-15, 15)

    j_list.append(j)
    k_list.append(k)

print("J list is: {} and K list is {}".format(j_list, k_list))

正如@ShadowRanger指出的那样,while循环策略对计算的要求较低,并且更易于阅读,因此您可能想要这样做。

答案 1 :(得分:0)

这里最好的解决方案不是过滤掉不良值,而是首先防止它们发生。一个简单的解决方案是生成一个更严格的数字范围(与整个范围一样大,减去要排除的数字),然后如果结果等于或大于结果的底数,则将省略数字的大小添加到结果中排除范围。

from random import randint

i = 10

j_list = []
k_list = []

too_close = 5    

while i != 0:

    j = randint(-10, 10)
    k = randint(-15, 15 - (too_close * 2 + 1))  # excluding j +- 5 means 11 numbers we won't use
    # The range from j - 5 to 4 is logically j + 6 to 15, so when we
    # generate a number of j - 5 or higher, we add 11 to adjust it to the desired result
    if k >= j - too_close:
        k += too_close * 2 + 1

    j_list.append(j)
    k_list.append(k)

    i -= 1

print("J list is: {} and K list is {}".format(j_list, k_list))

对于任何复杂程度的PRNG,这都应该在性能上取胜,因为这意味着您永远不会生成任何个随机数;因为您确保直接生成有效数字,所以没有“测试不良并生成新循环”之类的信息。

旁注:

i = 10
while i != 0:
    ...
    i -= 1

否则i未被使用是一种毫无意义的复杂拼写方式:

for i in range(10):
    ...

或者如果我必须从10降到0:

for i in range(10, 0, -1):
    ...

for的性能将胜过while,并且错误发生的可能性大大降低(不能忘记调整i或通过continue等跳过调整步骤) )。

答案 2 :(得分:-1)

如何遵循这些思路,您可以轻松更改iterations的数量,randint的范围以及randint之间的允许空间

from random import randint

def not_within_five(lista):
    i = 0
    while i < 10:
        x = randint(0, 50) 
        if lista[i] in range(x-5, x+5):
            continue
        else:
            lista.append(x)
            i += 1

j = []
k = []

j.append(randint(0, 50))
k.append(randint(0, 50))

not_within_five(j)
not_within_five(k)

print(f"J list is {j}\n")
print(f"K list is {k}")

输出

(xenial)vash@localhost:~/python$ python3.7 randi.py
J list is [19, 31, 49, 3, 9, 42, 29, 41, 22, 0, 35]

K list is [42, 19, 13, 27, 42, 1, 26, 10, 17, 40, 47]