zoukankan      html  css  js  c++  java
  • 【C】揭秘rand()函数;

    原文地址:http://www.cnblogs.com/ngnetboy/archive/2012/11/23/2784078.html

    相信只要是程序猿都会知道rand()函数是用来取随机数的一个库函数,但是它出的结果真的是一组随机数吗?我们来看看这段代码运行的结果:
    复制代码
     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 int main(void)
     4 {
     5     int j;
     6     for(j=0;j<5;j++)
     7     {
     8         printf("rand():%d
    ",rand());
     9     }    
    10 }
    复制代码

    linux下gcc每次运行结果如下:

    windows vc6.0每次运行结果如下:(本人windows系统为64位机)

    (由于编译器的不同,可能显示的结果也不同吧!)

    rand()函数不是随机的吗?怎么每次运行的结果都是一样的?其实计算机也不像人们想象的那么智能,它也是按照人们的思想来随机出数的。本人在linux下查找头文件没有找到rand()函数的定义,上网查了一下也没找到,说是被封装到库中了。若是有大牛们看到这篇文章,请帮帮小弟解决心中的疑问吧!

    那么如何用rand()函数获取你想要的取值范围呢?其实rand()函数的取值范围在0~RAND_MAX之间;

    那么什么是RAND_MAX呢?

    linux下的RAND_MAX值为2147483647(二进制32位)

    windows下的RAND_MAX值为32767(二进制16位)

    由此可见RAND_MAX是根据编译器对int型分配的空间而定的;这种说法应该也是错的,因为我在windows下的vc中打印sizeof(int)的值之后竟然显示4,也就是说int在vc中的存储空间应该是32位,所以我认为是vc编译器对rand()函数的定义做了修改,使RAND_MAX的值更小,方便了开发者的取值;(下面会介绍为什么编译器这样做)

    我们知道了rand()函数的取值范围后,如何取得你想要的数值范围呢?我们取0~10的值好了。正常的思路如下,10*rand()/(RAND_MAX+1)+1(用10乘以rand()取得的随机数,然后除以RAND_MAX,再加1),应该是这样的了。代码如下:

    复制代码
     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 int main(void)
     4 {
     5     int i;
     6     for(i=0;i<3;i++)
     7     {
     8       d=rand();
     9         c=1 + (10*d/(RAND_MAX));
    10         printf("1 + (10*rand()/(RAND_MAX+1)):%d
    ",c);
    11     }
    12     
    13 }
    复制代码

    运行结果如下:

    好像也达到我们的效果了。但是如果把这段代码放到linux下用gcc编译又是什么样的结果呢?

    同样的代码,我们来看看结果

    这是怎么回事?为什么同样的代码,到了另一个编译器后就不一样了?

    还记得我们刚才分别在这两个编译器中求的RAND_MAX的值吗?对,vc中是32767,而gcc中是2147483647。这时候你该问了跟这个有关系吗?我可以十分肯定的告诉你,相当的有关系。我们来写个小程序验证我的猜想吧!代码如下:

    复制代码
     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 int main(void)
     4 {
     5     int i,a,d;
     6     for(i=0;i<5;i++)
     7     {
     8         d=rand();        
     9         a=d*10;
    10         printf("%d",sizeof(int));
    11         printf("rand()*10:%d
    ",a);
    12     }    
    13 }
    复制代码

    运行结果如下:

    你看出有什么不一样了吗?对,这就是vc为什么对rand()函数的RAND_MAX的值进行修改了。在gcc中rand()的取值范围是0~32位的二进制数,如果拿这个随机数乘以10的话,很可能会发生数值溢出,也就是说gcc中int的值最大就取到2147483647,如果乘以10的话,只能接着往后排列了,-2147483647、-2147483646、-2147483645········一直到取得的那个值。所以会得到一些负数。

    到了这里我想你应该知道解决的办法了吧~!没错,就是用一个double类型的数来接收rand()*10,我们没办法改变RAND_MAX的值,我们可以用更大的数来表示rand()*10。

    这下应该可以了吧,我们修改一下代码看看效果:

    复制代码
     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 int main(void)
     4 {
     5     int i,a,d;
     6     for(i=0;i<5;i++)
     7     {      
     8         printf("(int)(10.0*rand()/(RAND_MAX+1.0)):%d
    ",1+(int)(10.0*d/(RAND_MAX+1.0)));
     9     }    
    10 }
    复制代码

    运行结果如下:

    对,这就是我们想要的结果了!

    PS——函数会随着编译器的不同而效果不同,但是它终究逃不过开发者的眼睛,注意细节。

    附加:

    取0-1之间的浮点型值:

    复制代码
     1 #include <stdio.h>
     2 #include<stdlib.h>
     3 #include<time.h>
     4 
     5 int main(void)
     6 { 
     7     int i;
     8     float a;
     9     srand((unsigned)time(NULL));
    10     for(i=0;i<10;i++)
    11     {
    12         printf("%.1f
    ",rand()/(RAND_MAX+0.1));
    13     }
    14 }    
    复制代码

    srand()函数是设置随机数的种子,由前面的推论可知rand()函数只是一个伪随机函数,srand()函数就是为rand()函数设置种子;time()函数是获取当前的时间,因此第九行代码就是为rand()函数设置一个根据系统时间变化的随机种子,这样代码在每次运行的时候的结果都不会一样了!

  • 相关阅读:
    C++进阶
    傅雷的一生
    OJ (Online Judge)使用
    详解事件委托
    tween.js是一款可生成平滑动画效果的js动画库。tween.js允许你以平滑的方式修改元素的属性值。它可以通过设置生成各种类似CSS3的动画效果。
    利用tween,使用原生js实现模块回弹动画效果
    JS阻止链接跳转代码
    CSS display 属性
    HTML5 Canvas绘文本动画(使用CSS自定义字体)
    MySQL基础CRUD编程练习题的自我提升(1)
  • 原文地址:https://www.cnblogs.com/leihupqrst/p/3487334.html
Copyright © 2011-2022 走看看