揭秘rand()函数

简介: 转载自: http://www.cnblogs.com/ngnetboy/archive/2012/11/23/2784078.html相信只要是程序猿都会知道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\n",rand());
 9     }    
10 }
复制代码

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

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

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

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_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*(rand()/(RAND_MAX*1.0))):%d\n",(int)(10*(d/(RAND_MAX*1.0)))); //rand value 0~10
 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()函数设置一个根据系统时间变化的随机种子,这样代码在每次运行的时候的结果都不会一样了!

如果没有设置srand,则每次运行程序,产生的随机数序列都是一样的。


目录
相关文章
overleaf 插入图片,引用图片,图标标题Fig与文章引用Figure不一致解决
overleaf 插入图片,引用图片,图标标题Fig与文章引用Figure不一致解决
8948 0
|
NoSQL Redis
Redis——大批量删除redis的key
Redis——大批量删除redis的key
220 1
|
编译器 C语言 C++
VSCode上搭建C/C++开发环境(vscode配置c/c++环境)Windows系统---保姆级教程
VSCode上搭建C/C++开发环境(vscode配置c/c++环境)Windows系统---保姆级教程
8793 0
|
SQL 资源调度 数据库连接
Hive怎么调整优化Tez引擎的查询?在Tez上优化Hive查询的指南
在Tez上优化Hive查询,包括配置参数调整、理解并行化机制以及容器管理。关键步骤包括YARN调度器配置、安全阀设置、识别性能瓶颈(如mapper/reducer任务和连接操作),理解Tez如何动态调整mapper和reducer数量。例如,`tez.grouping.max-size` 影响mapper数量,`hive.exec.reducers.bytes.per.reducer` 控制reducer数量。调整并发和容器复用参数如`hive.server2.tez.sessions.per.default.queue` 和 `tez.am.container.reuse.enabled`
1227 0
|
算法 安全 数据安全/隐私保护
【C/C++ 随机函数行为】深入探索C++中的随机数:std::random_device与rand的行为分析(一)
【C/C++ 随机函数行为】深入探索C++中的随机数:std::random_device与rand的行为分析
1089 0
|
存储 Ubuntu 测试技术
Ubuntu镜像源cn.arichinve.ubuntu.com不可用原因分析和解决
源配置的是cn.archive.ubuntu.com,但是发现,系统更新时,自动去找了清华大学的Ubuntu源。
6988 0
|
存储
5.3.1_原补码的乘法运算
计算机组成原理之原补码的乘法运算
563 2
5.3.1_原补码的乘法运算
|
JSON 缓存 NoSQL
重新更新VScode配置(C/C++)——负责任、手把手教学,亲测有效
对于C/C++的编程环境来说,目前我们所接触到的、所用到的,除了vim以外,大众用的、尤其是学生群体用的主要是有三种。
1643 1
重新更新VScode配置(C/C++)——负责任、手把手教学,亲测有效
|
算法 安全 Linux
Linux 中的 /dev/random 和 /dev/urandom 是什么?
Linux 中的 /dev/random 和 /dev/urandom 是什么?
469 0