日常业务中,经常会生成随机数,这里以C++为例,常见的随机数生成方法如下:原理很简单,先生成一个随机数生成器,指定种子,然后生成随机数;
#include#includeintmain(){printf("time(0)=%d",time(0));srand(0);for(inti=0;i<=10;i++){printf("%d\n",rand());}system("pause");}根据随机数的定义,每次生成的数不一样才能叫随机数。然而上面这段代码真是这样的么?我们看看效果了:生产的10个数确实不一样啊,这不就是我们想要的效果么?感兴趣的读者可以自行尝试多生成一些数,看看每次生成的数是不是都不一样!
我明明想生成随机数,为啥每次生成实例产生的数据都是一样的了?换句话说:srand生成随机数的原理是啥了?
#include#includeintmain(){intseed=time(0);printf("seed=%d",seed);srand(seed);for(inti=0;i<=10;i++){printf("%d\n",rand());}system("pause");}多运行几个实例,每次产生的数确实不一样了:这样就万事大吉、高枕无忧了?
前面说了:相同的种子,产生的伪随机数是一样的,是不是也可以反过来猜想:根据伪随机数倒推种子了?比如我先在看到的数字是22843、6380、25403、7962,是不是能倒推出种子是16210637719041了?一旦倒推出种子,我是不是也能成功预测第5个数字是13894了?穷举找seed的代码如下:
intnum[]={22843,6380,25403,7962};intseed=time(0);boolbfind=false;while(seed--){srand(seed);for(inti=0;i<4;i++){if(num[i]!=rand()){bfind=false;break;}bfind=true;}printf("%disnottheseed,continue!\n",seed);if(bfind){printf("findtheseed:%d\n",seed);break;}}一旦找到seed,就能用这个seed继续生成剩下的数字,准确预测了!
===================================分割线====================================
怎么才能得到尽可能随机的数了?这就要回到随机数的定义了!我个人简单理解:所谓随机数,就是没有规律、无法精准预测、琢磨不透生成规律的数!为了达到这个效果,这里“不走寻常路”地用多线程(不考虑同步)去读写数据,原因很简单:
机制越复杂,人为预测(甚至是猜测)准确的可能性就越小,这不就是“随机”要达到的效果么?所以这里尝试用多线程读写同一内存的方式生产随机数,核心代码如下:
#includeintnum=0;pthread_mutex_tmutex;void*inc_num(void*arg){//pthread_mutex_lock(&mutex);for(inti=0;i<=10000;i++){num++;}//pthread_mutex_unlock(&mutex);returnNULL;}void*dec_num(void*arg){//pthread_mutex_lock(&mutex);for(inti=0;i<=10000;i++){num--;}//pthread_mutex_unlock(&mutex);returnNULL;}voidmain(){pthread_mutex_init(&mutex,NULL);pthread_tthread_id[50];for(inti=0;i<50;i++){if(i%2){pthread_create(thread_id+1,NULL,inc_num,NULL);}else{pthread_create(thread_id+1,NULL,dec_num,NULL);}}for(inti=0;i<50;i++){pthread_join(thread_id[i],NULL);}printf("numis%d",num);pthread_mutex_destroy(&mutex);}代码的原理很简单:生成50个线程,奇数号线程增加num,偶数号线程减少num,但是线程完全不使用同步机制!由于上述的cpu缓存、os线程调度机制很复杂,人为预测准确的概率较小,反正我尝试过多次后还没遇到重复的结果!