生成一个少于 4 位数字但它具有 1、2 或 3 位数字的概率相等的随机数
Generate a random number less than 4 digits but the probability of it having 1, 2, or 3 digits is equal
我目前正在使用 1 + (int)(rand() * 999.0 / RAND_MAX)
生成介于 1 和 999 之间的随机数(含 1 和 999),但两位数和一位数的出现频率不如三位数。
我该如何解决这个问题?
请注意,虽然原始代码给出的范围是 0 到 999(含),但我实际上想要的范围是 1 到 999(含)。
您观察到一位数字的出现频率不如两位和三位数字出现的频率不足为奇。
一位数只有9个(不包括零),但两位数有90个,三位数有900个。所以统一的随机数生成器将以该频率抽取数字。
要生成 [1, 999] 范围内的随机数,使它们具有 1、2 和 3 位数字的概率相等,请使用您最喜欢的生成器生成随机数 p
,例如,在 [0, 1) 范围内(请参阅 C++ 中的新随机库函数来执行此操作),并使用 std::pow(1000, p);
.
对其进行转换
你要注意,得到的分布不会是piecewise-uniform:也就是说抽到某个位数的数字的概率是不一样的作为绘制具有该位数的任何其他数字的概率。但它确实有一个连续且可微的累积密度函数,这在数学上很重要。
(对于有数学倾向的人,我应用的转换是 OP 需要的分布的 quantile 函数)。
你也可以使用 if 语句,这样会快一点:
int m=rand();
if(m%3+1==3)
z=(int)rand()%900+100;
else if(m%3+1==2)
z=(int)rand()%90+10;
else if(m%3+1==1)
z=(int)rand()%10;
100,000,000 次重复的 clock()
差异是:
t_pow: 23912
t_if: 6640
if 和 pow 变体之间的分布差异:Plot in wolframalpha.com
您可以在一个使用 2 个随机数的语句中完成。将第一个乘以 10 ** 第二个。第二个是 1、2 或 3。这里是 Excel 公式:
=Int(Rand()*10^(int(Rand()*3)+1))
我目前正在使用 1 + (int)(rand() * 999.0 / RAND_MAX)
生成介于 1 和 999 之间的随机数(含 1 和 999),但两位数和一位数的出现频率不如三位数。
我该如何解决这个问题?
请注意,虽然原始代码给出的范围是 0 到 999(含),但我实际上想要的范围是 1 到 999(含)。
您观察到一位数字的出现频率不如两位和三位数字出现的频率不足为奇。
一位数只有9个(不包括零),但两位数有90个,三位数有900个。所以统一的随机数生成器将以该频率抽取数字。
要生成 [1, 999] 范围内的随机数,使它们具有 1、2 和 3 位数字的概率相等,请使用您最喜欢的生成器生成随机数 p
,例如,在 [0, 1) 范围内(请参阅 C++ 中的新随机库函数来执行此操作),并使用 std::pow(1000, p);
.
你要注意,得到的分布不会是piecewise-uniform:也就是说抽到某个位数的数字的概率是不一样的作为绘制具有该位数的任何其他数字的概率。但它确实有一个连续且可微的累积密度函数,这在数学上很重要。
(对于有数学倾向的人,我应用的转换是 OP 需要的分布的 quantile 函数)。
你也可以使用 if 语句,这样会快一点:
int m=rand();
if(m%3+1==3)
z=(int)rand()%900+100;
else if(m%3+1==2)
z=(int)rand()%90+10;
else if(m%3+1==1)
z=(int)rand()%10;
100,000,000 次重复的 clock()
差异是:
t_pow: 23912
t_if: 6640
if 和 pow 变体之间的分布差异:Plot in wolframalpha.com
您可以在一个使用 2 个随机数的语句中完成。将第一个乘以 10 ** 第二个。第二个是 1、2 或 3。这里是 Excel 公式:
=Int(Rand()*10^(int(Rand()*3)+1))