我试图在不使用增强的情况下在C中获得0到1之间的均匀随机数.我不想依赖图书馆.
每当我开始我的课程时,我都会:
srand(time(NULL));
然后我打印8个随机数.我用一个空白行分隔程序的不同运行:
Random number: 0.226063 Random number: 0.449186 Random number: 0.474514 Random number: 0.160779 Random number: 0.220868 Random number: 0.136685 Random number: 0.260120 Random number: 0.843334 Random number: 0.226181 Random number: 0.422253 Random number: 0.808594 Random number: 0.040531 Random number: 0.212377 Random number: 0.421073 Random number: 0.965790 Random number: 0.026305 Random number: 0.226306 Random number: 0.526858 Random number: 0.898279 Random number: 0.378934 Random number: 0.736653 Random number: 0.924420 Random number: 0.718503 Random number: 0.888140 Random number: 0.226463 Random number: 0.157614 Random number: 0.010386 Random number: 0.551936 Random number: 0.391998 Random number: 0.303603 Random number: 0.659396 Random number: 0.465434
为什么每次第一个数字几乎完全相同?我不明白.我应该把第一个号码丢掉还是什么?
示例代码:
#include <iostream> int main() { srand( time(NULL) ); printf("%f\n",(float)rand()/RAND_MAX); printf("%f\n",(float)rand()/RAND_MAX); }
解决方法
不,不要扔掉第一个.这会扭曲结果.序列{1,1,1}与任何其他任意七位数序列完全一样,尽管人类试图在所有事物中找到意义的倾向:-)
试图摆弄它因为你不喜欢这个序列会使随机数生成更糟,而不是更好.
对于它的价值,你应该确保你的运行至少间隔一秒,这样你就不会使用相同的种子(这似乎不是这里的情况).除此之外,使用PRNG按原样提供的结果或找到更好的发电机.
你是一个统计学家/密码学家,你不会使用正常的随机函数,或者它真的没关系!对于绝大多数情况,它是后者.
如果你不想要一个花哨的(或一个涉及大量额外的东西)并且你对实现提供的那个不满意,那么很容易实现一个基于gcc版本,如:
seed = (1103515245 * seed + 12345) & 0xffffffff return seed & 0x7fffffff
并且请记住,初始种子值是根据提供给srand的参数计算的,其模数为231-1,以最小化与初始种子具有线性相关性的序列(序列仍然是线性的,而不是来自初始种子值).
如果您只是在寻找快速解决方案而不依赖于外部库或花费时间实现更复杂的生成器,以下代码可能会让您的生活更轻松:
// Assume 32-bit integer. static int seed = 1; void mySRand (int newseed) { seed = newseed % 0x7fffffff; } int myRand() { seed = 1103515245 * seed + 12345; return seed & 0x7fffffff; }
以下程序实际上会让您了解该算法将对提供给mySRand的种子值的小变化做些什么.
它从时间获得初始种子(NULL),然后显示20个连续种子值的初始值超出myRand,以及百分比变化.
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <math.h> static int seed = 1; void mySRand (int newseed) { seed = newseed % 0x7fffffff; } int myRand() { seed = 1103515245 * seed + 12345; return seed & 0x7fffffff; } int main (void) { int i,xyzzy,val,lastVal; double avg,diff; xyzzy = time (NULL); mySRand (xyzzy); lastVal = myRand(); printf ("seed=%d,val=%12d\n",lastVal); for (i = 0; i < 20; i++) { mySRand (++xyzzy); val = myRand(); avg = val; avg = (avg + lastVal) / 2; diff = 100 * fabs (avg - val) / avg; printf ("seed=%d,val=%12d,avg=%12.1f,%%chg=%f\n",avg,diff); lastVal = val; } return 0; }
百分比变化基于当前值与当前值和之前的平均值之间的差异,以便有希望不引入偏差.示例输出是:
seed=1324533721,val= 1092183454 seed=1324533722,val= 48215051,avg= 570199252.5,%chg=91.544175 seed=1324533723,val= 1151730296,avg= 599972673.5,%chg=91.963792 seed=1324533724,val= 107761893,avg= 629746094.5,%chg=82.888041 seed=1324533725,val= 1211277138,avg= 659519515.5,%chg=83.660545 seed=1324533726,val= 167308735,avg= 689292936.5,%chg=75.727484 seed=1324533727,val= 1270823980,avg= 719066357.5,%chg=76.732504 seed=1324533728,val= 226855577,avg= 748839778.5,%chg=69.705726 seed=1324533729,val= 1330370822,avg= 778613199.5,%chg=70.864150 seed=1324533730,val= 286402419,avg= 808386620.5,%chg=64.571108 seed=1324533731,val= 1389917664,avg= 838160041.5,%chg=65.829626 seed=1324533732,val= 345949261,avg= 867933462.5,%chg=60.141039 seed=1324533733,val= 1449464506,avg= 897706883.5,%chg=61.463005 seed=1324533734,val= 405496103,avg= 927480304.5,%chg=56.279815 seed=1324533735,val= 1509011348,avg= 957253725.5,%chg=57.639642 seed=1324533736,val= 465042945,avg= 987027146.5,%chg=52.884483 seed=1324533737,val= 1568558190,avg=1016800567.5,%chg=54.264095 seed=1324533738,val= 524589787,avg=1046573988.5,%chg=49.875518 seed=1324533739,val= 1628105032,avg=1076347409.5,%chg=51.262038 seed=1324533740,val= 584136629,avg=1106120830.5,%chg=47.190523 seed=1324533741,val= 1687651874,avg=1135894251.5,%chg=48.574735
所以你可以看到,基于靠近的初始种子,起始值实际上存在很大差异.