原文地址: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\n",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\n",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\n",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\n",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\n",rand()/(RAND_MAX+0.1));
13 }
14 }

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

【C】揭秘rand()函数;的更多相关文章

  1. srand()以及rand()函数用法

    srand()就是给rand()提供种子seed 如果srand每次输入的数值是一样的,那么每次运行产生的随机数也是一样的, srand(n) for(10) rand()也就是说,以一个固定的数值作 ...

  2. MySQL使用rand函数实现随机数[转]

    如何写一个语句能一下更新几百条MYSQL数据! 需要测试MYSQL数据库,里面有一个上万条数据的数据库,如何写一个PHP文件一下每次更新几百条信息,我都是写一个循环一次更新一条信息,这样我知道用WHI ...

  3. Matlab中Rand()函数用法

    一.理论准备 matlab函数randn:产生均值为0,方差 σ^2 = 1,标准差σ = 1的正态分布的随机数或矩阵的函数. 用法:Y = randn(n),返回一个n*n的随机项的矩阵.如果n不是 ...

  4. 关于 rand() 函数返回值的值域的疑问

    <C语言参考手册>中关于 rand() 函数有如下描述. (1)rand() 函数的原型 int rand(void); (2)连续调用 rand 将返回 0 到 int 类型的最大可表示 ...

  5. C random C ++rand函数应用

    random函数不是ANSI C标准,不能在gcc,vc等编译器下编译通过.但在C语言中int random(num)能够这样使用,它返回的是0至num-1的一个随机数. 可改用C++下的rand函数 ...

  6. RAND函数和SRAND函数

    首先我们要对rand&srand有个总体的看法:srand初始化随机种子,rand产生随机数,下面将详细说明. rand(产生随机数) 表头文件: #include<stdlib.h&g ...

  7. C语言中生产随机数 rand()函数

    参考资料:C语言中产生随机数 一:如果你只要产生随机数而不需要设定范围的话,你只要用rand()就可以了:rand()会返回一随机数值, 范围在0至RAND_MAX 间.RAND_MAX定义在stdl ...

  8. 关于rand()函数 转载于其他人

    C++中的rand()函数 分类: 编程语言/ C#/ 文章 C++中产生随机数种子对于初学者一直都很困惑.大家知道,在C中有专门的srand(N)函数可以轻松实现这一功能,然而在C++中则要复杂一些 ...

  9. mysql的rand函数

    项目中需要动态随机生成一些固定位数的随机数,如8位,5位等. 之前看到的写法是这样 ROUND(ROUND(RAND(),5)*100000) 这样写不太准确,有几率出现4位的情况,Rand() 函数 ...

随机推荐

  1. php 随机生成汉字

    function getChar($num) // $num为生成汉字的数量 { $b = ''; for ($i=0; $i<$num; $i++) { // 使用chr()函数拼接双字节汉字 ...

  2. js面试必考:this

    this是前端面试中必考的基础知识点,也是新手小白在做项目中经常晕头转向的问题.但其实this不难理解. 判断this指向时,记住以下几点: 判断函数类型, 1.1 如果是箭头函数,则为第一个包裹箭头 ...

  3. ElementUI el-message 提示信息的用法

    引入message Element 注册了一个$message方法用于调用,Message 可以接收一个字符串或一个 VNode 作为参数,它会被显示为正文内容. Element 为 Vue.prot ...

  4. Java基础 -4.3

    While循环结构 while循环 public static void main(String[] args) { while(布尔表达式) { 条件满足时执行; 修改循环条件; } } do wh ...

  5. Python函数-2 匿名函数

    匿名函数 当我们在创建函数时,有些时候,不需要显式地定义函数,直接传入匿名函数更方便.这省去了我们挖空心思为函数命名的麻烦,也能少写不少代码,很多编程语言都提供这一特性. Python语言使用lamb ...

  6. ORACLE varchar2类型的字段更改为clob

    将varchar2类型字段改成clob类型    --增加临时新字段 alter table base_temp add temp clob; --将需要改成大字段的项内容copy到大字段中updat ...

  7. ubutun18 install ibus-pinyin

    ref: https://www.cnblogs.com/asmer-stone/p/9069866.html Step1 $ sudo apt-get install ibus-pinyin

  8. python中metaclass的工作原理

    class TMetaclass(type): def __new__(cls, name, bases, attrs): print(cls, name, bases, attrs) return ...

  9. python之闭包,装饰器

    目录 函数对象 :相当于变量名 函数对象的作用: 1. 可以引用 2. 可以作为函数的返回值 3. 可以作为容器的元素 4. 可以作为函数的参数 闭包 定义: 如果在一个函数的内部定义了另一个函数,外 ...

  10. 吴裕雄--天生自然JAVAIO操作学习笔记:投票程序

    public class ExecDemo{ public static void main(String args[]){ new Operate() ; } }; import java.io.B ...