生成小于4位的随机数,但其具有1,2或3位的概率相等

18 c++ random distribution

我目前正在使用1 + (int)(rand() * 999.0 / RAND_MAX)生成1到999之间的随机数,但两位数和一位数不会像三位数一样频繁出现.

我怎样才能解决这个问题?

请注意,虽然原始代码的范围为0到999(含),但我实际上需要1到999的范围.

Bat*_*eba 29

您发现一位数字不会出现两位数和三位数的情况并不令人惊讶.

只有9个一位数字(不包括零),但有90个两位数字,900个三位数字.因此,统一的随机数生成器将在该频率中绘制数字.

要生成[1,999]范围内的随机数,使其具有1,2和3位数的概率相等,请使用您喜欢的生成器生成一个随机数p,例如,在[0,1]范围内(请参阅C++中的新随机库函数来执行此操作),并使用它进行转换std::pow(1000, p);.

您应该注意,生成的分布不是分段统一的:也就是说,绘制具有一定数字位数的数字的概率与绘制具有该数字位数的任何其他数字的概率不同.但它确实具有连续且可微分的累积密度函数,这在数学上是重要的.

(对于数学倾向,我正在应用的变换是OP需要的分布的分位数函数).

  • 任何考虑这个解决方案的人都应该注意到它不是**均匀分布.获得1比9的可能性高9倍,获得10比9的可能性高9倍9倍,比999获得100倍的可能性高10倍.而且你根本不会得到零. (26认同)

Fot*_*ysk 20

你也可以使用更快一点的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;
Run Code Online (Sandbox Code Playgroud)

clock()100,000,000次重复的差异是:

t_pow: 23912
t_if: 6640
Run Code Online (Sandbox Code Playgroud)

使用时钟滴答测试代码以进行性能分配 - IF, POW

if和pow变体之间的分布差异:在wolframalpha.com上绘制