使用概率分布扩展整数的随机范围
Expand random range of integers using probability distribution
我试图解决生成 1 到 7 之间的随机整数的经典问题,给定一个生成 1 到 5 之间的随机整数的函数。
我的方法是将 2 次调用的结果添加到 rand5(),有效地将其转化为 "sum of dice rolls" 问题。骰子总和的概率很容易计算,所以我在这里使用它。对此的解释在代码
之后
我的问题是:如何计算计数器的值应该是多少?经实验验证,当前值不正确。是否存在满足概率的整数值?并且有没有更好的办法用这种方法来解决这个问题?
def rand5():
return random.randint(1,5)
def rand7():
counter = [1,2,3,4,5,4,3]
while 0 not in counter:
sum = rand5() + rand5() - 2
if sum <= 6:
counter[sum] -= 1
return counter.index(0) + 1
作为参考,出现以下代码以创建随机分布。
test_counter = [0,0,0,0,0,0,0,0,0,0,0,0]
for i in range(500000):
test_counter[rand5() + rand5() - 2] += 1
test_counter[0] *= 60
test_counter[1] *= 30
test_counter[2] *= 20
test_counter[3] *= 15
test_counter[4] *= 12
test_counter[5] *= 15
test_counter[6] *= 20
test_counter[7] *= 0
test_counter[8] *= 0
print(test_counter)
概率说明:可以通过列出可能的骰子组合来计算掷骰子的概率。对于这个问题,每个 die(rand5 函数)生成的数字将是:
{(1,1), (1,2), (1,3), (1,4), (1,5), (2,1), (2,2), .. ., (5,5)}
每个和的概率是该和在列表中出现的方式数除以列表中的项目总数。该列表总共有 5^2 = 25 个元素。例如和为4可以通过以下组合{(1,3), (2,2), (3,1)},所以和为4的概率是3/25.
则每个结果的概率为:
- 1/25
- 2/25
- 3/25
- 4/25
- 5/25
- 4/25
- 3/25
- 2/25
- 1/25
我尝试使用此分布来生成统一分布,方法是必须多次生成更常见的分布,并将其存储在计数器中。
不确定通过骰子分配是个好主意。通常,如果您有随机位源,但序列较短,则最好将位组合并切碎以组成更长的随机位序列。沿线
import random
def rand5():
return random.randint(1, 5)
def twobits():
q = rand5() - 1 # [0...5) range
while q == 4: # dropping high bit
q = rand5() - 1
return q # [0...3) range, two random bits
def onebit():
return twobits() & 1
def rand7():
q = onebit() << 2 | twobits() # here we have [0...8) range
while q == 0: # and dropping 0
q = onebit() << 2 | twobits()
return q
counter = 8*[0]
for i in range(500000):
counter[rand7()] += 1
print(counter)
在 [1...8) 抽样中生产制服
[0, 71592, 71352, 71071, 71543, 71600, 71388, 71454]
从一个样本中取出两位,从另一个样本中取出一位,将它们组合起来,一些拒绝,瞧!
我试图解决生成 1 到 7 之间的随机整数的经典问题,给定一个生成 1 到 5 之间的随机整数的函数。 我的方法是将 2 次调用的结果添加到 rand5(),有效地将其转化为 "sum of dice rolls" 问题。骰子总和的概率很容易计算,所以我在这里使用它。对此的解释在代码
之后我的问题是:如何计算计数器的值应该是多少?经实验验证,当前值不正确。是否存在满足概率的整数值?并且有没有更好的办法用这种方法来解决这个问题?
def rand5():
return random.randint(1,5)
def rand7():
counter = [1,2,3,4,5,4,3]
while 0 not in counter:
sum = rand5() + rand5() - 2
if sum <= 6:
counter[sum] -= 1
return counter.index(0) + 1
作为参考,出现以下代码以创建随机分布。
test_counter = [0,0,0,0,0,0,0,0,0,0,0,0]
for i in range(500000):
test_counter[rand5() + rand5() - 2] += 1
test_counter[0] *= 60
test_counter[1] *= 30
test_counter[2] *= 20
test_counter[3] *= 15
test_counter[4] *= 12
test_counter[5] *= 15
test_counter[6] *= 20
test_counter[7] *= 0
test_counter[8] *= 0
print(test_counter)
概率说明:可以通过列出可能的骰子组合来计算掷骰子的概率。对于这个问题,每个 die(rand5 函数)生成的数字将是:
{(1,1), (1,2), (1,3), (1,4), (1,5), (2,1), (2,2), .. ., (5,5)}
每个和的概率是该和在列表中出现的方式数除以列表中的项目总数。该列表总共有 5^2 = 25 个元素。例如和为4可以通过以下组合{(1,3), (2,2), (3,1)},所以和为4的概率是3/25.
则每个结果的概率为:
- 1/25
- 2/25
- 3/25
- 4/25
- 5/25
- 4/25
- 3/25
- 2/25
- 1/25
我尝试使用此分布来生成统一分布,方法是必须多次生成更常见的分布,并将其存储在计数器中。
不确定通过骰子分配是个好主意。通常,如果您有随机位源,但序列较短,则最好将位组合并切碎以组成更长的随机位序列。沿线
import random
def rand5():
return random.randint(1, 5)
def twobits():
q = rand5() - 1 # [0...5) range
while q == 4: # dropping high bit
q = rand5() - 1
return q # [0...3) range, two random bits
def onebit():
return twobits() & 1
def rand7():
q = onebit() << 2 | twobits() # here we have [0...8) range
while q == 0: # and dropping 0
q = onebit() << 2 | twobits()
return q
counter = 8*[0]
for i in range(500000):
counter[rand7()] += 1
print(counter)
在 [1...8) 抽样中生产制服
[0, 71592, 71352, 71071, 71543, 71600, 71388, 71454]
从一个样本中取出两位,从另一个样本中取出一位,将它们组合起来,一些拒绝,瞧!