Python:生成两个相差至少为k的随机整数

时间:2017-07-27 18:04:26

标签: python python-3.x

如何在range(n, m)中生成两个随机整数,其中nm相差至少k(即abs(n-m) >= k)?我可以想到两个解决方案(它们在下面),但第一个解决方案可能变得不切实际,大k个,而第二个解决方案偏向于n或{{1等于mlower

upper-1

5 个答案:

答案 0 :(得分:3)

我们可以使用一点数学来使解决方案更简单。如果我们要求从a, b中选择随机数range(m, n)abs(b-a) >= k,则我们知道a必须位于range(m, n-k)b必须在range(m+k,n)

因此,我们首先选择a,然后从符合条件的可用选项子集中选择b:

a = random.randint(m, n-k)
b = random.randint(a+k, n)

请注意,上述答案并未对所有可能的a,b组合进行同等抽样

这是一个改进的解决方案,它将对所有组合赋予相同的权重:

while(True):
    a = random.randint(m,n-k)
    b = random.randint(m+k,n)
    if abs(b-a) >= k:
        break

答案 1 :(得分:1)

def randiff_sample(lower, upper, min_diff):
    if upper - lower < min_diff:
        raise ValueError("upper - lower should be larger than the minimum required difference")

    a = random.randint(lower, upper-min_diff -1)
    b = random.randint(a+min_diff, upper)
    return a,b

答案 2 :(得分:1)

通过选择一个随机整数并应用一些算术,可以获得合适的对。

使用lower = 0upper = 10min_diff = 5,可能的对是:

[(0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (1, 6), (1, 7), (1, 8), (1, 9), (2, 7), (2, 8), (2, 9), (3, 8), (3, 9), (4, 9)]

它们形成三角形:

enter image description here

这意味着计算number of possible pairs很容易。也可以使用"Cantor pairing function"为这些对中的每一对分配一个数字。

此功能可以颠倒:从随机整数z开始,可以获得(x,y)对。

将这些全部放在一起,代码变为:

from math import floor, sqrt
from random import randrange

def reverse_cantor(z):
    w = int(floor((sqrt(8 * z + 1) - 1) / 2)) # see https://en.wikipedia.org/wiki/Pairing_function#Inverting_the_Cantor_pairing_function
    t = (w**2 + w) // 2
    y = z - t
    x = w - y
    return (x, y)

def pick_random(lower, upper, min_diff):
    height = upper - lower - min_diff
    count = height * (height + 1) // 2
    z = randrange(0, count)
    x, y = reverse_cantor(z)
    a = lower + x
    b = upper - 1 - y
    return (a, b)

通过创建150000个随机对来检查分布是否正确:

from collections import Counter

dist = Counter(pick_random(0, 10, 5) for _ in range(150000))

import matplotlib.pyplot as plt
import numpy as np

labels, values = zip(*sorted(dist.items()))

indexes = np.arange(len(labels))
width = 1

plt.bar(indexes, values, width)
plt.xticks(indexes, labels)
plt.show()

enter image description here

每一对都非常接近出现10000次。

这是使用接受的解决方案的第一种方法计算的分布: enter image description here

答案 3 :(得分:0)

def get_random(lower, upper, k):
    num1 = random.randint(lower, upper)
    try:
        if upper - num1 < k:
            num2 = random.randint(lower, num1 - k)
        else:
            num2 = random.choice([random.randint(num1 + k, upper), random.randint(lower, num1 - k)])
    except ValueError:
        return get_random(lower, upper, k)
    return num1, num2

这是我的解决方案。

答案 4 :(得分:0)

在这种情况下,更好的解决方案取决于您所寻找的差异的大小。如果范围很宽并且您期望的差异很小,则可以轻松实现。在下面的解决方案中,我已将范围差异除以所需的限制。

import random 
def randomGen(upper, lower, min_diff):
    if (upper - lower) <= min_diff:
        raise ValueError ('Not possible to calculate')
    else:
        print ((upper - lower) // min_diff)
        if (upper - lower) // min_diff >= 1:
            x = random.randint(lower, int((-(min_diff/2) + (lower + upper)/2)))
            y = random.randint(int(((lower + upper)/2) + min_diff/2), upper )
            print (x,y)

min_diff = 200   
upper = 480
lower = 279

randomGen(upper, lower, min_diff)