C语言中用于产生随机数的函数使用方法总结


在UNIX操作系统和window的操作系统上,我们知道有一个函数rand,它就是用来产生随机数的函数API接口,那么它的原理如何实现?
如果约定a1=f(seed),an+1=f(an),那么可以得到一个序列a1,a2,a3..an,那么要制作一个伪随机函数rand,只需要让它每调用一次就返回序列的下一个元素就行。其实就是相当于第1次调用rand返回a1,第2次返回a2,…,第n次返回an,这样每次返回的数值都不一样,也就是相当于随机数了。但是其实不是真正的随机数,真正的随机数是使用物理现象产生的:比如掷钱币、骰子、转轮、使用电子元件的噪音、核裂变等等。这样的随机数发生器叫做物理性随机数发生器,它们的缺点是技术要求比较高。那到底什么是随机数呢?

随机数:随机数就是每次运行代码的时候随机产生的数,每次产生的数的值是无法确定的,返回 0 到 RANDMAX 之间的随机整数值,不包含 RANDMAX 的值,RANDMAX 的范围最少是在32767之间(int),即双字节(16位数)。若用 unsigned int 双字节是65535,四字节是4294967295的整数范围。而且 0 到 RANDMAX 每个数字被选中的概率是相同的。

原理:产生随机数的原理是根据一个值,一般称为随机种子,然后把这个种子作为参数,经过一系列的公式运算产生出一个值,这个值就是随机数。

在 C 语言当中使用随机数要用到 rand 函数和 srand 函数,

int rand():返回值为随机值,参数为空,通过 rand 函数就会产生一个随机数。

void srand(unsigned int seed):返回值为空, 就是设置随机种子的,当我们不设置随机种子的时候,默认设置的种子为 1,也就是srand(1)。

使用:

#include<stdlib.h>//得引入 stdlib.h 这个头文件
int main()
{
 int rand_num = rand();
 printf("rand_num = %d\n", rand_num);
 return 0;
}

每次运行的结果都一样,这是为什么呢?上面已经说了,随机数产生的是有一个随机种子作为参数,然后返回一个值,而且默认的随机种子为1,所以每次产生的随机数都一样。

如果我们修改一下随机种子,会发现随机数和原来的不一样了,但是每次运行的结果还是一样:

#include<stdlib.h>//得引入 stdlib.h 这个头文件
int main()
{
 srand(3);
 int rand_num = rand();
 printf("rand_num = %d\n", rand_num);
 srand(5);
 rand_num = rand();
 printf("rand_num = %d\n", rand_num);
 return 0;
}

两次的输出结果不一样,我的输出结果如下:

rand_num = 50421

rand_num = 847425747

但是我们程序肯定是写好之后,不改动随机种子,然后每次产生不同的值才对啊,那我们来如何做呢?既然产生的随机值与种子有关,只要每次的随机种子不一样,那么产生的随机值也不一样,我们就可以把时间作为随机种子,因为每次运行时,时间都不一样,因此产生的随机值也不一样,因此我们可以这样:

#include<time.h> //使用 time 函数必须引入 time.h 头文件
#include<stdlib.h>
int main()
{
 srand((int)time(0));
 int rand_num = rand();
 printf("rand_num = %d\n", rand_num);
 return 0;
}

这样的话,每次输出结果都不一样了。

通过上面的方法,我们可以获取不同的随机值了,但是我们一般会获取一定范围内的随机值,比如返回 0~100 之间的返回值,比如模拟骰子,随机返回 1~6 的值。那么我们该如何做呢?

我们要返回 0~6 的随机值,只需在上面返回随机值的地方对 7 取余即可:

int rand_num = rand() % 7;
printf("rand_num = %d\n", rand_num);

所以我们如果要返回 0~a 的随机值,只要对 a + 1 取余即可,所以有下面的公式:

int rand_num = rand() % (a + 1);//返回 0 ~ a 的随机值

如果我们要返回 a ~ b 的随机值,公式是什么呢?因为随机数取余法只能返回 0 到某个数的随机值,所以 a ~ b 的随机值,我们可以先返回 0 ~ (b – a)的随机值,然后再加上 a 即可:

int rand_num = rand() % (b - a + 1);//1、返回 0 ~ (b - a)的随机值
rand_num = rand_num + a; //2、返回 a ~ b 的随机值

因此上面的 1 和 2 合并之后的公式为:

int rand_num = rand() % (b - a + 1) + a;//返回 a ~ b 的随机值

大家现在做这样的操作:

#include<stdlib.h>
int main()
{
 srand(2);//随机种子固定为2
 for(int i = 0; i < 5; i++)
 {
 int rand_num = rand();
 printf("rand_num = %d\n", rand_num);//注意输出结果  
 }
 return 0;
}

既然随机种子一样,为什么输出结果不一样呢?这里得注意一下,如果程序没有结束,而且也没有重新设置过随机种子,那么系统会把上次的随机值作为下次随机函数的随机种子,因此在上面的 for 循环当中,其实每次的循环种子都不一样,怎么验证呢?先看我这里的输出结果为:

rand_num = 33614

rand_num = 564950498

rand_num = 1097816499

rand_num = 1969887316

rand_num = 140734213

我们可以把随机种子设置成其中的一个 rand_num 值,比如 33614,那么输出结果如果为 564950498 的话,那么说明在 for 循环中每次都把随机值作为下次的随机函数的随机种子了。

srand(33614);
int rand_num = rand();
printf("rand_num = %d\n", rand_num);

结果:

rand_num = 564950498;

验证完毕。

arc4random() 函数:

这个函数是 C 语言封装的一个比较智能的随机函数,我们只要调用这个函数,就会产生随机数,不用设置随机种子,而且用法很简单:

int arc_rand = arc4random();
printf("arc_rand = %d\n", arc_rand);

每次的运行结果都不一样。如果要产生 a ~ b 的随机值,公式也是:

arc4random() % (b - a + 1) + a;



相关阅读:
js将当前时间格式转换成时间搓(自写)
使用GruntJS构建Web程序之Tasks(任务)篇
MongoDB中的bson介绍和使用实例
Java的Struts框架中的主题模板和国际化设置
C++设计模式之单例模式
JavaScript中使用ActiveXObject操作本地文件夹的方法
android照相、相册获取图片剪裁报错的解决方法
查看修改mysql编码方式让它支持中文(gbk或者utf8)
使用PHP和HTML5 FormData实现无刷新文件上传教程
三星笔记本(910S3K-K03)U盘装win7系统图文教程 三星笔记本u盘装win7
Javascript刷新窗口方法小结
jquery实现左右滑动菜单效果代码
微软正在内测win10 Build 10550版本 有望推送快速版
win10 Build 10108版本截图图赏:UI新的改进
快速导航
PHP MySQL HTML CSS JavaScript MSSQL AJAX .NET JSP Linux Mac ASP 服务器 CMS SQL jQuery C# C++ java Android IOS oracle MongoDB PostgreSQL SQLite 交通频道 G4722 G1875 G215 G569 G421 G6733 G7577 G8906 G1235 G4916 G7291 G1953 G245 G662 G1570 G6285 G719 G1836 G1346 G4781 G4908 G289 G6781 G9290 G7358 G1928 G1815 G325 G132 G4901 G6012 G6290 G7131 G5367 G184 G151 G5303 G1136 G6481 G7028 G575 G1744 G7660 G7693 G2344 G4937 G1234 G1814 G6252 G1492 G253 G2926 G883 G9275 G1231 G556 G241 G1306 G7646 G8103 G600 G1858 G9678 G6160 G7156 G825 G1125 G7249 G1809 G1350 G432 G9466 G7067 G785 G6404 G4663 G7008 G150 G823 G1514 G7529 G1201 G2353 G205 G7629 G9409 G6147 G677 G390 G8016 G9239 G456 G828 G8045 G491 G7145 G397 G7012 G1021 G6482 G2322 G7264 G1301 G9247 G96 G1294 G7133 G4824 G7005 G1653 G5307 G1213 G822 G4837 G1422 G411 G6227 G1571 G359 G1882 G6074 G7678 G21 G7077 G1272 G8918 G9645 G461 G1254 G1846 G8021 G7303 G1104 G76 G82 G621 G218 G8533 G2341 G8543 G555 G8013 G4802 G1364 G1153 G1342 G1861 G8905 G590 G4780 G668 G9261 G1304 G1638 G1395 G2914 G8003 G7158 G1833 G1873 G8128 G1856 G1841 G8709 G7346 G4612 G2103 G835 G8712 G381 G7240 G8932 G507 G29 G4054 G6273 G6752 G426 G211 G9473 G7119 G2333 G1567 G6153 G360 G4011 G5301 G7648 G8010 G8015 G6706 G614 G423 G8557 G9465 G72 G6018 G8901 G7030 G123

丹东 云霄 辽中 德阳 克拉玛依 惠山 招远 昭通 铁岭西 延吉西 军粮城北 定西 晋中 许昌东 郫县 诏安 七台河 高碑店东 南昌 延安 敦化 铜陵北 嵩明 鲘门 扬中 龙里北 舟山 洛阳 运城北 鞍山 西昌 邵阳北 绍兴 白山 三明 肇东 陵水 衡山西 嘉善 宜都 泰兴 泉州 汉口 东胜西 昌图西 锦州南 安阳东 怀化 黄南 亚龙湾 扬州 温州 南翔北 福安 金山北 永川东 安达 曲阜东 郑州西 天门 绍兴北 涪陵北 阳泉北 三亚 葫芦岛北 徐州 阳江 辽源 新泰 阿坝 孝感北 三穗 金寨 保山 高安 安阳 牟平 西双版纳 信阳 繁昌西 哈尔滨北 达州 新余 沈阳南 四平 扶余北 伊宁 郴州西 济源 水家湖 民权北 福鼎 如皋 奉化 全州南 安庆 太姥山 武汉 乐清 皮口 武昌 茂名 邯郸 资阳 马鞍山 三水南 泰安 包头东 衡阳东 南丰 仙桃西 安吉 罗源 山海关 平湖 惠州 资阳北 淄博 丹阳 莱州 巴东 关岭 盐城 锦州 格尔木 益阳 大英东 吉林 湛江 临安 襄汾西 渑池南 当涂东 辽阳 徐水 贺州 韶关 光明城 邯郸东 普安县 南江口 铜川 五龙背东 张家港 烟台南 萍乡北 青堆 长乐 江门 台州 衡水 湘潭北 闽清北 高邑西 盖州西 石柱县 潮汕 肇庆 泰康 邵东 湖州 余姚 平凉 宜宾 增城 沧州 都匀 防城港 鹰潭北 海东西 福田 余姚北 岳池 广州北 南安 蓬莱 瓦房店西 李石寨 葛店南 海安 无锡东 上饶 通辽 四会 桂林西 砀山南 兰州 滨海 龙口 绅坊 莱西 石林西 深圳 大连北 成都 上海西 孝感 杏树屯 德清 嘉兴

Copyright © 2016 phpStudy |