原文地址: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. python开发接口

    享一段代码,开发了3个接口:            1.上传文件            2.查看所有文件            3.下载文件 使用python开发,需要安装flask模块,使用pip ...

  2. git push的时候报错: Out of memory, malloc failed (tried to allocate 82037333 bytes)

    原因:上传的文件过大,这里我上传的文件有10G+所以报了上面的错误 解决方法:依次运行:git config --global pack.threads 1 git,git config --glob ...

  3. 02-03Android学习进度报告三

    今天主要学习了线性布局和相对布局的概念和区别,以及线性布局和相对布局的优缺点. 经过搜素发现,我们屏幕适配的使用用的比较多的就是LinearLayout的权重属性weight,我 学习了一些 Line ...

  4. web组件化开发第一天

    技术选型 html5 css3 jq 应用的插件 FullPage.js 一.建一个测试页面,测试静态的功能 <!DOCTYPE html> <html> <head&g ...

  5. Linux centosVMware PHP动态扩展模块

    PHP动态扩展模块 /usr/local/php/bin/php -m //查看模块 下面安装一个redis的模块 cd /usr/local/src/ wget https://codeload.g ...

  6. Eth合约攻击续

    合同代表一个非常简单的游戏:谁给它发送了比当前奖金还大的数量的以太,就成为新的国王.在这样的事件中,被推翻的国王获得了新的奖金,但是如果你提交的话那么合约就会回退,让level重新成为国王,而我们的目 ...

  7. 题解 P3950 【部落冲突】

    树链剖分吼啊 一看就看出是LCT模板题啦 前记 见这么多人写LCT,却很少人写树链剖分,于是我就来一发树链剖分(其实是因为自己不会LCT) 本蒟蒻的写法和诸位写树链剖分的大神有点不同 思路 树链剖分, ...

  8. Lesson 10 Silicon valley

    What does the computer industry thrive on apart from anarchy? Technology trends may push Silicon Val ...

  9. jqGrid一次性读取本地数据

    参考:http://blog.sina.com.cn/s/blog_54da57aa010154r7.html

  10. 标准模板库中的队列(queue)

    //C++数据结构与算法(第4版) Adam Drozdek 著  徐丹  吴伟敏<<清华大学出版社>> 队列容器默认由deque实现,用户也可以选择list容器来实现.如果用 ...