为什么C ++ rand()似乎只能生成相同数量级的数字?
在用C / C ++编写的一个小应用程序中,我正面临rand
函数的问题,可能是种子:
我想产生一系列不同顺序的随机数字,即不同的对数值(基数2)。 但似乎所有的数字都是相同的,在2 ^ 25和2 ^ 30之间波动。
是不是因为rand()
是用Unix时间播种,现在是一个相对较大的数字? 我忘了什么 我在main()
的开头只播放一次rand()
main()
。
1到2 30之间只有3%的数字不在2 25和2 30之间 。 所以,这听起来很正常:)
因为2 25/2 30 = 2 -5 = 1/32 = 0.03125 = 3.125%
较浅的绿色是0和2 25之间的区域; 深绿色是2 25和2 30之间的区域。 蜱是2的幂。
你需要更精确:你需要不同的基数2对数值,但你想要什么分布 ? 标准rand()函数产生一个统一的分布,你将需要使用与你想要的分布相关的分位数函数来转换这个输出。
如果你告诉我们分配,那么我们可以告诉你需要的quantile
函数。
如果你想要不同的数量级,为什么不试试pow(2, rand())
? 或者,也可以像哈罗德(Harold)所build议的那样直接selectrand()
@ C4stor提出了一个伟大的观点。 但是,对于一个更一般的情况,人们更容易理解(基数10):对于从1到10 ^ n的范围,约90%的数字是从10 ^(n-1)到10 ^ n,因此, 99%的数字从10 ^(n-2)到10 ^ n。 保持添加尽可能多的小数点,只要你想要的。
有趣的math,如果你一直这样做,你可以看到,从1到10 ^ n, 99.9999 …%= 100%的数字是从10 ^ 0到10 ^ n这种方法。
现在关于代码,如果你想要一个随机数字,从0到10 ^ n的随机数量级,你可以这样做:
-
生成一个从0到n的小随机数
-
如果知道n的范围,则生成一个大的随机数10 ^ k,其中k> max {n}。
-
剪下较长的随机数,得到这个大随机数的n个数字。
基本的(和正确的)答案已经在上面被接受和接受了: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样本)频率的直方图:
0和2 ^ 29和2 ^ 29和2 ^ 30之间的数字完全相同。
考虑问题的另一种方法是:考虑产生的随机数的二进制表示,最高位为1的概率等于1/2,因此,在半数情况下得到29。 你想要的是看到一个低于2 ^ 25的数字,但是这意味着5个最高位全部为零,这发生在1/32的低概率上。 有机会,即使你运行了很长时间,你永远也看不到15以下的顺序(概率是连续滚动6次)。
现在,你关于种子的问题的一部分。 不,种子不可能确定数字生成的范围,它只是确定第一个,最初的元素。 将rand()看作是范围内所有可能数字的序列(预定置换)。 种子确定从序列开始绘制数字的位置。 这就是为什么如果你想要(伪)随机性,你用当前的时间来初始化序列:你不关心你的起始位置是不均匀分布的,重要的是你永远不会从同一个位置开始。
使用pow(2,rand())
它会给出所需数量级的答案!
如果你想使用在线服务的随机数字,你可以使用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