在用C / C ++编写的小应用程序中,我遇到了rand
函数和种子的问题:
我想生成一系列具有不同顺序的随机数,即具有不同的对数值(基数2)。但似乎所有产生的数字都是相同的,在2 ^ 25和2 ^ 30之间波动。
是因为rand()
是用Unix时间播种的,现在是一个相对较大的数字?我忘记了什么?
我只在rand()
的开头播种main()
。
答案 0 :(得分:478)
在1和2 30 之间仅有3%的数字不在2 25 和2 30 之间。所以,这听起来很正常:)
因为2 25 / 2 30 = 2 -5 = 1/32 = 0.03125 = 3.125%
答案 1 :(得分:272)
浅绿色是0到2 25 之间的区域;较深的绿色是2 25 和2 30 之间的区域。刻度是2的幂。
答案 2 :(得分:42)
您需要更精确:您需要不同的基数2对数值,但您想要的是什么分布?标准rand()函数生成均匀分布,您需要使用与所需分布关联的分位数函数来转换此输出。
如果您告诉我们分发,那么我们可以告诉您所需的quantile
功能。
答案 3 :(得分:18)
如果您想要不同的数量级,为什么不尝试pow(2, rand())
?或者像哈罗德建议的那样直接选择顺序为rand()?
答案 4 :(得分:13)
@ 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,你可以这样做:
从0到n生成一个小的随机数
如果您知道n具有的范围,则生成10 ^ k的大随机数,其中k>最大{N}。
剪下较长的随机数,得到这个大随机数的n位数。
答案 5 :(得分:13)
上面已经给出并接受了基本(和正确)答案: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到2的数字(128到255的均匀,256到1023的密度的一半等),分布将是均匀的。
这是数字0到31(在1M样本中)的频率的直方图:
答案 6 :(得分:5)
0到2 ^ 29和2 ^ 29和2 ^ 30之间的数字完全相同。
另一种看待问题的方法:考虑你生成的随机数的二进制表示,最高位为1的概率等于1/2,因此,在一半的情况下得到29阶。你想要的是看到一个低于2 ^ 25的数字,但这意味着5个最高位都是零,这发生在1/32的低概率。有可能即使你长时间运行它,你也永远不会看到低于15的顺序(概率就像连续滚动6次一样)。
现在,关于种子问题的一部分。不,种子不可能确定生成数字的范围,它只是确定第一个初始元素。将rand()视为范围内所有可能数字的序列(预定排列)。种子确定从序列中开始绘制数字的位置。这就是为什么如果你想要(伪)随机性,你可以使用当前时间来初始化序列:你不关心你开始的位置是不是均匀分布,重要的是你永远不会从相同的位置开始。
答案 7 :(得分:2)
使用
pow(2,rand())
它将按照所需幅度给出答案!!
答案 8 :(得分:2)
如果您想使用在线服务中的随机数,您可以使用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