你有一个函数f1()以相等的概率生成0或1。编写一个函数f200(),使用f1()生成介于1到200之间(包括两者)的数字。
有人建议采用以下方法:投掷硬币并根据结果确定数字是否超过一半或少于一半。每半个递归一次。选择一半是以2的幂完成的。
选择2的权力的原因是我们可以实现所有数字吗?
import random as rd
def prob200(half):
if half >= 200:
return 0
#f1 can be replaced by this rd.randint(0, 1)
toss_value = f1()
# check if toss falls in this current half and then change the half for next recursion.
# we change half from 1, 2, 4, 8, 16, 36, 64, 128
result = toss_value*half + prob200(half<<1)
if result > 200:
return prob200(1)
else:
return result
for i in range(0, 10):
print(prob200(1))
答案 0 :(得分:1)
使用随机位生成器创建一个带有n位的数字x(例如n = 32或更高,如果需要更高的精度=更均匀的分布),您可以将其转换为所需的范围r(例如r = 200),如下所示:result = floor(x / 2 ^ n * r)+1
例如,如果使用n = 8,则使用随机位生成器(函数f1)生成一个8位数,该生成器的范围为0-255(含)。然后你将它除以2 ^ 8 = 256,所以我们将得到一个0到255/256之间的数字。然后我们乘以200,所以我们将得到0到199.2之间的结果。最后,我们将其向下舍入并添加1以获得1到200之间的数字。
但是因为我们只使用了8个randoms位(n = 8),所以unifrmity并不是那么好。我们有效地生成了0-255(源范围)的数字,并将其转换为1-200(目标范围)的数字。目标范围中的大多数数字在源范围中具有一个对应的数字,但是其他数字(例如数字1)具有两个对应的源编号(0和1)。因此,有些数字的概率为1/256,而其他数字的概率为2/256。
为了改善这一点,我们可以使用n = 16,然后概率差异最多为1/2 ^ 16。
这是一个首先尝试使用8位生成随机数的程序,但如果它溢出4次,则会使用我描述的方法生成32位数并将其转换为输出范围:
import math
import random
def f1():
return random.randint(0,1)
def rand_by_bits(n):
v=0
for i in range(n):
v=(v<<1)+f1()
return v
def rand_by_range(r):
n=0
t=r
while t>0:
t>>=1
n+=1
for i in range(4):
v=rand_by_bits(n)
if v<r:
break
if v>=r:
n=32
v=math.floor(float(rand_by_bits(n))/(1<<n)*r)
return v+1
def main():
random.seed()
print(rand_by_range(200))
答案 1 :(得分:0)
选择2的幂来均匀分布生成的随机数。
让我们首先明确一个数字是2的幂是否无关紧要。我们总能“实现所有数字”。
每次你有2个半数时,你有相同的概率选择一半(因为 f1()生成0或1,概率相等)。这显然意味着我们不会选择2个中的一半,因此我们总能实现所有数字。
现在问题是为什么那么我应该选择2的力量?
我会回答说,如果你不选择2的幂,那么你会得到随机数,但概率不等。
该案例的一个简短例子应该清楚,我在这里:
让我们假设你必须生成1到3范围内的数字。现在,当你将它的一半时,你将它切成1 2。 3或1 | 2 3.让我们说你做的就像1 | 2 3.
因此,选择1的概率将变为1/2 = 0.5,选择2或3的概率将变为1/2 * 1/2 = 0.25
问题的根源在于,当大小范围不等于2的幂时,将该范围(1到3分成1 | 2 3)分成2组。你得到2组不等的大小(组1的大小为1,组2的大小为2)。这种群体规模的变化将导致这些群体中数字选择概率的变化。
但是如果数字的幂为2,则可以保证您将始终获得相同大小的组。所以,它总会给你一个概率相等的随机数。
Q.E.D。
答案 2 :(得分:-1)
这是我怎么做的。 给定f(0,1),您可以为任何x生成随机数f(0,2 ^ x - 1)。 对于n = 200,生成函数f(0,255)。 然后r = f(0,255),如果r < 200返回r。 否则,重新运行算法,例如重新生成r直到r小于200.