【题目】
给定一个等概率产生1~5的随机函数 rand1To5如下:
def rand1To5():
return int(random.random()*5) + 1
除此之外,不使用任何额外的随机机制,请用rand1To5实现等概率随机产生1~7的随机函数rand1To7。
【补充题目】
给定一个以p概率产生0,以1-p概率产生1的随机函数rand01p如下:
def rand01p():
p = 0.83 #p可以随意改变
return 0 if random.random() < p else 1
除此之外,不使用任何额外的随机机制,请用rand01p实现等概率随机产生1~6的随机函数rand1To6。
【进阶题目】
给定一个等概率随机产生1~M的随机函数rand1ToM如下:
def rand1ToM(m):
return int(random.random() * m) + 1
除此之外,不能使用任何额外的随机机制。有两个输入参数,分别为m和n,请用rand1ToM(m)实现等概率随机产生1~n的随机函数rand1ToN。
【基本思路】
原问题。
1、rand1To5() 等概率产生1,2,3,4,5
2、rand1To5()-1 等概率产生0,1,2,3,4
3、(rand1To5()-1)*5 等概率的产生0,5,10,15,20
4、(rand1To5()-1)*5+rand1To5()-1 等概率的产生0,1,2,3…23,24
5、如果步骤4产生的结果大于20,重新随机,直到产生的结果在0~20之间。
6、步骤5的结果再进行%7,然后再加1,就是最终的结果。
#python3.5
def rand1To5():
return int(random.random()*5) + 1
def rand1To7():
num = (rand1To5()-1) * 5 + rand1To5() - 1
while num > 20:
num = (rand1To5()-1) * 5 + rand1To5() - 1
return num % 7 + 1
补充题目。
虽然rand01p方法是以p的概率产生0,以1-p的概率产生1,但是rand01p产生01和10的概率却都是p(1-p),可以利用这点来实现等概率随机产生0和1的函数。
def rand01():
num = rand01p()
while num == rand01p():
num = rand01p()
return num
有了等概率产生0和1的函数,接下来的步骤和原问题类似。先实现随机产生0~3的随机函数,再利用0~3的随机函数实现随机产生1~6的随机函数。
def rand01p():
p = 0.83
return 0 if random.random() < p else 1
def rand01():
num = rand01p()
while num == rand01p():
num = rand01p()
return num
def rand0To3():
return rand01()*2 + rand01()
def rand1To6():
num = rand0To3() * 4 + rand0To3()
while num > 11:
num = rand0To3() * + rand0To3()
return num % 6 + 1
进阶题目。
1、将n-1转换成m进制数,假设结果转换成数组为 k = [a,b,c,d,e]
2、使用rand1ToM(m)函数产生结果数组 res = [A,B,C,D,E],如果res所表示的数值大于k所表示的数值,将res丢掉重新随机,直到产生的结果小于或等于k,这时产生的res的范围就在0~n-1之间,但是此时res所表示的数还是m进制的。
3、将res数组转换成10进制整数。
4、将步骤3的结果加1就是最终的结果。
def rand1ToM(m):
return int(random.random() * m) + 1
def rand1ToN(n, m):
def getMSysNum(value, m):
res = []
while value != 0:
res.append(value % m)
value //= m
return res[::-1]
def getRandMSysNumLessN(nMSys, m):
res = []
lastEqual = True
index = 0
while index < len(nMSys):
res.append(rand1ToM(m) - 1)
if lastEqual:
if res[-1] > nMSys[index]:
index = 0
res = []
continue
else:
lastEqual = True if res[-1] == nMSys[index] else False
index += 1
return res
def getNumFromMSysNum(mSysNum, m):
res = 0
for i in range(len(mSysNum)):
res = res * m + mSysNum[i]
return res
nMSys = getMSysNum(n-1, m)
randNum = getRandMSysNumLessN(nMSys, m)
return getNumFromMSysNum(randNum, m) + 1