zoukankan      html  css  js  c++  java
  • 随机数真的是随机的么? ---让菠菜、*等裤衩赔穿的漏洞

      日常业务中,经常会生成随机数,这里以C++为例,常见的随机数生成方法如下:原理很简单,先生成一个随机数生成器,指定种子,然后生成随机数;

    #include <iostream>
    #include <windows.h>
    
    int main()
    {
        printf("time(0)=%d",time(0));
        srand(0);
        for(int i=0;i<=10;i++){
            printf("%d
    ",rand());
        }
        system("pause");
        
    }

      根据随机数的定义,每次生成的数不一样才能叫随机数。然而上面这段代码真是这样的么?我们看看效果了:生产的10个数确实不一样啊,这不就是我们想要的效果么? 感兴趣的读者可以自行尝试多生成一些数,看看每次生成的数是不是都不一样!

      

            然而这样就结束了么?图样图森破!同样的代码,我们多运行几次实例看看了,效果如下:不同的时间点我生成了4个不同的实例,然后每次生成实例产生的随机数都是一样的,这是不是很“毁三观”啊!

      

       我明明想生成随机数,为啥每次生成实例产生的数据都是一样的了?换句话说:srand生成随机数的原理是啥了?

       计算机的随机数都是由伪随机数,即是由小M多项式序列生成的,其中产生每个小序列都有一个初始值,即随机种子。(注意: 小M多项式序列的周期是65535,即每次利用一个随机种子生成的随机数的周期是65535,当你取得65535个随机数后它们又重复出现了。)我们知道 rand() 函数可以用来产生随机数,但是这不是真正意义上的随机数,是一个伪随机数,是根据一个数(我们可以称它为种子)为基准以某个递推公式推算出来的一系列数,当这系列数很大的时候,就符合正态公布,从而相当于产生了随机数,但这不是真正的随机数,所以我们运行不同实例时产生的“随机数”居然是一样的,都是相同种子惹的祸!所以我们把种子用当前时间来代替,重新更改后的代码如下:

    #include <iostream>
    #include <windows.h>
    
    int main()
    {
        int seed = time(0);
        printf("seed=%d", seed);
        srand(seed);
        for(int i=0;i<=10;i++){
            printf("%d
    ",rand());
        }
        system("pause");
    }

      多运行几个实例,每次产生的数确实不一样了:这样就万事大吉、高枕无忧了?

        

         前面说了:相同的种子,产生的伪随机数是一样的,是不是也可以反过来猜想: 根据伪随机数倒推种子了?比如我先在看到的数字是22843、6380、25403、7962,是不是能倒推出种子是16210637719041了?一旦倒推出种子,我是不是也能成功预测第5个数字是13894了?穷举找seed的代码如下:

    int num[] = { 22843,6380,25403,7962 };
        int seed = time(0);
        bool bfind = false;
        while (seed--) 
        {
            srand(seed);
            for (int i=0;i<4;i++) 
            {
                if (num[i]!=rand()) 
                {
                    bfind = false;
                    break;
                }
                bfind = true;
            }
            printf("%d is not the seed,continue!
    ", seed);
            if (bfind) 
            {
                printf("find the seed:%d 
    ", seed);
                break;
            }
               
        }

      一旦找到seed,就能用这个seed继续生成剩下的数字,准确预测了!

      注意:实战时,因为不知道菠菜站点启动服务器的时间,所以这个计算量较大,一般都是用服务器+多线程跑的,这里只是介绍最核心的原理,感兴趣的小伙伴可以自行尝试!

    1、https://www.runoob.com/w3cnote/cpp-rand-srand.html  C++ rand 与 srand 的用法

  • 相关阅读:
    Codeforces G. Ciel the Commander
    点分治模板
    Codeforces I. Vessels(跳转标记)
    Codeforces C. Maximum Value(枚举二分)
    Codeforces D. Little Elephant and Interval(思维找规律数位dp)
    [USACO15DEC]最大流Max Flow(树上差分)
    Codeforces E. Alyona and a tree(二分树上差分)
    一致性Hash算法
    零拷贝
    Maven 指定范围依赖
  • 原文地址:https://www.cnblogs.com/theseventhson/p/14771241.html
Copyright © 2011-2022 走看看