zoukankan      html  css  js  c++  java
  • C++随机数生成方法(转载,赶紧搜藏)

    一、C++中不能使用random()函数

    ==================================================================================

    本文由青松原创并依GPL-V2及其后续版本发放,转载请注明出处且应包含本行声明。

    C++中常用rand()函数生成随机数,但严格意义上来讲生成的只是伪随机数(pseudo-random integral number)。生成随机数时需要我们指定一个种子,如果在程序内循环,那么下一次生成随机数时调用上一次的结果作为种子。但如果分两次执行程序,那么由于种子相同,生成的“随机数”也是相同的。

    在工程应用时,我们一般将系统当前时间(Unix时间)作为种子,这样生成的随机数更接近于实际意义上的随机数。给一下例程如下:

    #include <iostream>
    #include <ctime>
    #include <cstdlib>
    using namespace std;

    int main()
    {
        double random(double,double);
        srand(unsigned(time(0)));
        for(int icnt = 0; icnt != 10; ++icnt)
            cout << "No." << icnt+1 << ": " << int(random(0,10))<< endl;
        return 0;
    }

    double random(double start, double end)
    {
        return start+(end-start)*rand()/(RAND_MAX + 1.0);
    }
    /* 运行结果
    * No.1: 3
    * No.2: 9
    * No.3: 0
    * No.4: 9
    * No.5: 5
    * No.6: 6
    * No.7: 9
    * No.8: 2
    * No.9: 9
    * No.10: 6
    */
    利用这种方法能不能得到完全意义上的随机数呢?似乎9有点多哦?却没有1,4,7?!我们来做一个概率实验,生成1000万个随机数,看0-9这10个数出现的频率是不是大致相同的。程序如下:
    #include <iostream>
    #include <ctime>
    #include <cstdlib>
    #include <iomanip>
    using namespace std;

    int main()
    {
        double random(double,double);
        int a[10] = {0};
        const int Gen_max = 10000000;
        srand(unsigned(time(0)));
       
        for(int icnt = 0; icnt != Gen_max; ++icnt)
            switch(int(random(0,10)))
            {
            case 0: a[0]++; break;
            case 1: a[1]++; break;
            case 2: a[2]++; break;
            case 3: a[3]++; break;
            case 4: a[4]++; break;
            case 5: a[5]++; break;
            case 6: a[6]++; break;
            case 7: a[7]++; break;
            case 8: a[8]++; break;
            case 9: a[9]++; break;
            default: cerr << "Error!" << endl; exit(-1);
            }
       
        for(int icnt = 0; icnt != 10; ++icnt)
            cout << icnt << ": " << setw(6) << setiosflags(ios::fixed) << setprecision(2) << double(a[icnt])/Gen_max*100 << "%" << endl;
       
        return 0;
    }

    double random(double start, double end)
    {
        return start+(end-start)*rand()/(RAND_MAX + 1.0);
    }
    /* 运行结果
    * 0: 10.01%
    * 1:   9.99%
    * 2:   9.99%
    * 3:   9.99%
    * 4:   9.98%
    * 5: 10.01%
    * 6: 10.02%
    * 7: 10.01%
    * 8: 10.01%
    * 9:   9.99%
    */
    可知用这种方法得到的随机数是满足统计规律的。

    另:在Linux下利用GCC编译程序,即使我执行了1000000次运算,是否将random函数定义了inline函数似乎对程序没有任何影响,有理由相信,GCC已经为我们做了优化。但是冥冥之中我又记得要做inline优化得加O3才行...

    不行,于是我们把循环次数改为10亿次,用time命令查看执行时间:
    chinsung@gentoo ~/workspace/test/Debug $ time ./test
    0: 10.00%
    1: 10.00%
    2: 10.00%
    3: 10.00%
    4: 10.00%
    5: 10.00%
    6: 10.00%
    7: 10.00%
    8: 10.00%
    9: 10.00%

    real    2m7.768s
    user    2m4.405s
    sys     0m0.038s
    chinsung@gentoo ~/workspace/test/Debug $ time ./test
    0: 10.00%
    1: 10.00%
    2: 10.00%
    3: 10.00%
    4: 10.00%
    5: 10.00%
    6: 10.00%
    7: 10.00%
    8: 10.00%
    9: 10.00%

    real    2m7.269s
    user    2m4.077s
    sys     0m0.025s

    前一次为进行inline优化的情形,后一次为没有作inline优化的情形,两次结果相差不大,甚至各项指标后者还要好一些,不知是何缘由...

    =================================================================================


         random函数不是ANSI C标准,不能在gcc,vc等编译器下编译通过。 可改用C++下的rand函数来实现。     1、C++标准函数库提供一随机数生成器rand,返回0-RAND_MAX之间均匀分布的伪随机整数。 RAND_MAX必须至少为32767。rand()函数不接受参数,默认以1为种子(即起始值)。 随机数生成器总是以相同的种子开始,所以形成的伪随机数列也相同,失去了随机意义。(但这样便于程序调试)
          2、C++中另一函数srand(),可以指定不同的数(无符号整数变元)为种子。但是如果种子相同,伪随机数列也相同。一个办法是让用户输入种子,但是仍然不理想。
         3、 比较理想的是用变化的数,比如时间来作为随机数生成器的种子。 time的值每时每刻都不同。所以种子不同,所以,产生的随机数也不同。
    // C++随机函数(VC program)
    #include <stdio.h>
    #include <iostream>
    #include <time.h>
    using namespace std;
    #define MAX 100
    int main(int argc, char* argv[])
    {        srand( (unsigned)time( NULL ) );//srand()函数产生一个以当前时间开始的随机种子.应该放在for等循环语句前面 不然要很长时间等待
       for (int i=0;i<10;i++)
       cout<<rand()%MAX<<endl;//MAX为最大值,其随机域为0~MAX-1
       return 0;
    }
    二、rand()的用法
         rand()不需要参数,它会返回一个从0到最大随机数的任意整数,最大随机数的大小通常是固定的一个大整数。 这样,如果你要产生0~10的10个整数,可以表达为:
      int N = rand() % 11;
         这样,N的值就是一个0~10的随机数,如果要产生1~10,则是这样:
      int N = 1 + rand() % 10;
      总结来说,可以表示为:
      a + rand() % n
         其中的a是起始值,n是整数的范围。   a + rand() % (b-a+1) 就表示 a~b之间的一个随机数若要0~1的小数,则可以先取得0~10的整数,然后均除以10即可得到随机到十分位的10个随机小数,若要得到随机到百分位的随机小数,则需要先得到0~100的10个整数,然后均除以100,其它情况依此类推。
         通常rand()产生的随机数在每次运行的时候都是与上一次相同的,这是有意这样设计的,是为了便于程序的调试。若要产生每次不同的随机数,可以使用srand( seed )函数进行随机化,随着seed的不同,就能够产生不同的随机数。
         如大家所说,还可以包含time.h头文件,然后使用srand(time(0))来使用当前时间使随机数发生器随机化,这样就可以保证每两次运行时可以得到不同的随机数序列(只要两次运行的间隔超过1秒)。

  • 相关阅读:
    POJ 1141 括号匹配 DP
    881. Boats to Save People
    870. Advantage Shuffle
    874. Walking Robot Simulation
    文件操作
    861. Score After Flipping Matrix
    860. Lemonade Change
    842. Split Array into Fibonacci Sequence
    765. Couples Holding Hands
    763. Partition Labels
  • 原文地址:https://www.cnblogs.com/finallyliuyu/p/1848130.html
Copyright © 2011-2022 走看看