为什么 c + + rand()似乎只生成相同数量级的数字?

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

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

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

10113 次浏览

只有3% 的数字介于1和230之间,而不是介于225和230之间。所以,这听起来很正常:)

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

您需要更精确一些: 您需要不同的基数2对数值,但是您需要什么样的 分配?标准的 rand ()函数生成一个统一的分布,您需要使用与所需分布关联的 分位数函数来转换这个输出。

如果你告诉我们分布,然后我们可以告诉你的 quantile函数,你需要。

如果你想要不同的数量级,为什么不简单地试试 pow(2, rand())呢?或者像哈罗德建议的那样,直接选择兰德() ?

@ C4stor 说得很有道理。但是,对于更一般的情况和更容易理解的人类(以10为基数) : 对于范围从1到10 ^ n,约90% 的数字是从10 ^ (n-1)到10 ^ n,因此,约99% 的数字从10 ^ (n-2)到10 ^ n。

有趣的数学,如果你对 n 继续这样做,你可以看到从1到10 ^ n,用这个方法,数字的 99.9999% = 100% 是从10 ^ 0到10 ^ n。

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

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

  2. 如果你知道 n 的范围,生成一个10 ^ k 的大随机数,其中 k > max { n }。

  3. 剪掉较长的随机数,得到这个大随机数的 n 位数。

浅绿色是介于0和225之间的区域; 深绿色是介于225和230之间的区域。虱子的幂是2。

distribution

在0到2 ^ 29和2 ^ 29到2 ^ 30之间的数字数量是完全相等的。

另一种看待这个问题的方法是: 考虑你生成的随机数的二进制表示,最高位为1的概率等于1/2,因此,在一半情况下,你得到29次方。你想看到的是一个小于2 ^ 25的数字,但这意味着5个最高位都是0,这发生的概率很低,是1/32。机会是,即使你运行它很长一段时间,你将永远不会看到15以下的顺序在所有(概率是类似滚动66次在一行)。

现在,你关于种子的问题。不,种子不可能确定生成数字的范围,它只能确定第一个初始元素。可以将 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 个样本中) :

enter image description here

如果您想使用在线服务中的随机数,您可以使用 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

Http://programmingconsole.blogspot.in/2013/11/a-better-and-different-way-to-generate.html