给定一个函数,它产生的是1到5之间的随机整数,写一个函数,它产生的是1到7之间的随机整数。
当前回答
就是这样,均匀分布,零rand5调用。
def rand7:
seed += 1
if seed >= 7:
seed = 0
yield seed
需要事先播种。
其他回答
Python:有一个简单的两行答案,它使用空间代数和模量的组合。这不是直观的。我对它的解释令人困惑,但却是正确的。
知道5*7=35 7/5 = 1余数为2。如何保证余数之和始终为0?5*[7/5 = 1余数2]——> 35/5 = 7余数0
想象一下,我们有一条丝带,缠在一根周长为7的杆子上。丝带需要35个单位才能均匀地缠绕。随机选择7个色带片段len=[1…5]。忽略换行的有效长度与将rand5()转换为rand7()的方法相同。
import numpy as np
import pandas as pd
# display is a notebook function FYI
def rand5(): ## random uniform int [1...5]
return np.random.randint(1,6)
n_trials = 1000
samples = [rand5() for _ in range(n_trials)]
display(pd.Series(samples).value_counts(normalize=True))
# 4 0.2042
# 5 0.2041
# 2 0.2010
# 1 0.1981
# 3 0.1926
# dtype: float64
def rand7(): # magic algebra
x = sum(rand5() for _ in range(7))
return x%7 + 1
samples = [rand7() for _ in range(n_trials)]
display(pd.Series(samples).value_counts(normalize=False))
# 6 1475
# 2 1475
# 3 1456
# 1 1423
# 7 1419
# 4 1393
# 5 1359
# dtype: int64
df = pd.DataFrame([
pd.Series([rand7() for _ in range(n_trials)]).value_counts(normalize=True)
for _ in range(1000)
])
df.describe()
# 1 2 3 4 5 6 7
# count 1000.000000 1000.000000 1000.000000 1000.000000 1000.000000 1000.000000 1000.000000
# mean 0.142885 0.142928 0.142523 0.142266 0.142704 0.143048 0.143646
# std 0.010807 0.011526 0.010966 0.011223 0.011052 0.010983 0.011153
# min 0.112000 0.108000 0.101000 0.110000 0.100000 0.109000 0.110000
# 25% 0.135000 0.135000 0.135000 0.135000 0.135000 0.135000 0.136000
# 50% 0.143000 0.142000 0.143000 0.142000 0.143000 0.142000 0.143000
# 75% 0.151000 0.151000 0.150000 0.150000 0.150000 0.150000 0.151000
# max 0.174000 0.181000 0.175000 0.178000 0.189000 0.176000 0.179000
面对这么复杂的答案,我觉得自己很蠢。
为什么不能:
int random1_to_7()
{
return (random1_to_5() * 7) / 5;
}
?
简单高效:
int rand7 ( void )
{
return 4; // this number has been calculated using
// rand5() and is in the range 1..7
}
(灵感来自你最喜欢的“程序员”卡通?)
int randbit( void )
{
while( 1 )
{
int r = rand5();
if( r <= 4 ) return(r & 1);
}
}
int randint( int nbits )
{
int result = 0;
while( nbits-- )
{
result = (result<<1) | randbit();
}
return( result );
}
int rand7( void )
{
while( 1 )
{
int r = randint( 3 ) + 1;
if( r <= 7 ) return( r );
}
}
我玩了一下,我为这个Rand(7)算法写了“测试环境”。例如,如果你想尝试哪种分布给你的算法,或者需要多少次迭代才能生成所有不同的随机值(对于Rand(7) 1-7),你可以使用它。
我的核心算法是:
return (Rand5() + Rand5()) % 7 + 1;
和亚当·罗森菲尔德的分布一样均匀。(我将其包含在代码片段中)
private static int Rand7WithRand5()
{
//PUT YOU FAVOURITE ALGORITHM HERE//
//1. Stackoverflow winner
int i;
do
{
i = 5 * (Rand5() - 1) + Rand5(); // i is now uniformly random between 1 and 25
} while (i > 21);
// i is now uniformly random between 1 and 21
return i % 7 + 1;
//My 2 cents
//return (Rand5() + Rand5()) % 7 + 1;
}
这个“测试环境”可以采用任何Rand(n)算法并测试和评估它(分布和速度)。只需将代码放入“Rand7WithRand5”方法并运行代码片段。
一些观察:
亚当·罗森菲尔德(Adam Rosenfield)的算法并不比我的算法分布得更好。不管怎样,两种算法的分布都很糟糕。 本机Rand7(随机的。Next(1,8))完成,因为它在大约200+迭代中生成了给定间隔内的所有成员,Rand7WithRand5算法的顺序为10k(约30-70k) 真正的挑战不是编写从Rand(5)生成Rand(7)的方法,而是生成几乎均匀分布的值。