C++ 为什么C++;兰德()似乎只生成相同数量级的数字?

C++ 为什么C++;兰德()似乎只生成相同数量级的数字?,c++,c,math,random,C++,C,Math,Random,在一个用C/C++编写的小应用程序中,我遇到了rand函数的问题,可能还有种子: 我想产生一个顺序不同的随机数序列,即具有不同的对数值(以2为底)。但似乎所有产生的数字都是相同的顺序,在2^25和2^30之间波动 是不是因为rand()是以Unix时间为种子的,而Unix时间现在是一个相对较大的数字?我忘了什么? 我在rand()的开头只播了一次main()在1到230之间的数字中,只有3%不在225到230之间。所以,这听起来很正常:) 因为225/230=2-5=1/32=0.03125=3

在一个用C/C++编写的小应用程序中,我遇到了
rand
函数的问题,可能还有种子:

我想产生一个顺序不同的随机数序列,即具有不同的对数值(以2为底)。但似乎所有产生的数字都是相同的顺序,在2^25和2^30之间波动

是不是因为
rand()
是以Unix时间为种子的,而Unix时间现在是一个相对较大的数字?我忘了什么?
我在
rand()
的开头只播了一次
main()

在1到230之间的数字中,只有3%不在225到230之间。所以,这听起来很正常:)


因为225/230=2-5=1/32=0.03125=3.125%

你需要更精确:你想要不同的2进制对数值,但你想要什么样的分布?标准的rand()函数生成均匀分布,您需要使用与所需分布关联的分位数函数来转换此输出


如果您告诉我们分布,那么我们可以告诉您所需的
分位数
函数。

如果您想要不同的数量级,为什么不试试
pow(2,rand())
?或者像哈罗德建议的那样,直接选择rand()作为顺序?

@C4stor提出了一个很好的观点。但是,对于更一般的情况和更容易理解的人类(基数10):对于从1到10^n的范围,约90%的数字是从10^(n-1)到10^n,因此,约99%的数字是从10^(n-2)到10^n。继续添加任意多的小数

有趣的数学,如果你一直这样做n,你可以看到从1到10^n,用这个方法,数字的数量是从10^0到10^n

关于代码,如果你想要一个数量级为0到10^n的随机数,你可以:

  • 生成一个从0到n的小随机数

  • 如果您知道n的范围,那么生成一个顺序为10^k的大随机数,其中k>max{n}

  • 剪切较长的随机数,以获得此大随机数的n位数


  • 浅绿色是介于0和225之间的区域;深绿色是介于225和230之间的区域。滴答声是2的幂


    在0和2^29之间以及2^29和2^30之间有完全相等的数字

    查看问题的另一种方法:考虑生成的随机数的二进制表示,最高比特为1的概率等于1/2,因此,在半个情况下,你得到订单29。你想看到的是一个低于2^25的数字,但这意味着5个最高位都是零,发生的概率很低,为1/32。即使运行很长时间,也可能永远看不到低于15的订单(概率有点像连续滚动6次)

    现在,你问题中关于种子的部分。不,种子不可能确定生成数字的范围,它只确定第一个初始元素。把rand()看作是范围内所有可能数字的序列(预先确定的排列)。种子确定从序列开始绘制编号的位置。这就是为什么如果你想要(伪)随机性,你可以使用当前时间来初始化序列:你不在乎你开始的位置是否均匀分布,重要的是你从不从同一个位置开始
    pow(2,rand())
    它将按所需的数量级给出答案

    上面已经给出并接受了基本(正确)答案:0到9之间有10个数字,10到99之间有90个,100到999之间有900个,等等

    为了获得近似对数分布的分布,您需要将随机数右移一个随机数:

    s = rand() & 31; // a random number between 0 and 31 inclusive, assuming RAND_MAX = 2^32-1
    r = rand() >> s; // right shift
    
    它并不完美,但比计算pow(2,rand()*scalefactor)
    快得多。这将是“块状”的,因为系数2内的数字分布将是均匀的(128到255的分布是均匀的,256到1023的分布是密度的一半,等等)

    以下是数字0到31的频率直方图(在1M样本中):


    如果您想使用在线服务中的随机数,可以使用wget,您可能需要查看 您还可以使用诸如random.org之类的服务生成随机数,您可以使用wget捕捉它们,然后从下载的文件中读取数字

    wget -q https://www.random.org/integers/?num=100&min=1&max=100&col=5&base=10&format=html&rnd=new -O new.txt
    

    是的,说得好!2^25和2^30之间的数字比1和2^25之间的数字多31倍:)谢谢你的快速回答。我需要重新考虑一下这个计划。问题回答:@ TalaRon MaTaMaS考虑通过“代码> > <代码/>位移来截断数字,这将给你更小的数字。(或者用
    %
    取一个模)我希望这对大多数程序员来说是显而易见的:任何小于2^25的无符号整数的前7位必须等于
    0
    -如果每个位都是随机的…@BlueRaja DannyPflughoeft-如果概率很明显,赌场不景气。@布雷特尔-我不认为程序员是赌场的目标人口统计。所以,是C还是C++?如果用C/C++表示你可以使用C++,提到C是随机的,也许这能帮助你。不幸的是,你的赌注是错误的。种子不应该是你的问题。您的问题是错误的预期分布。由于无偏见的编程人员希望
    rand()
    返回均匀分布的数字(谷歌排名高的文档明确地这样说),所以我认为这个问题对未来的读者没有用处。这就是为什么否决投票,但不要让它阻止你使用SO。@doug65536“…在没有数字重复的地方”-这不是随机的!我可以在cr为我的退休提供资金