C语言中的随机数
作者:王璐
随机数,顾名思义就是随机产生的、无规则的数。在编程中,有时我们不想手动从键盘输入数据,而想让电脑自动产生一些数据供我们使用(例如生成100个两位数),就要用到随机数。
随机数的生成方法很简单,在C语言中,我们通过调用随机函数rand()来产生随机数。rand函数是C语言的标准库函数,和我们常用的输入输出函数(scanf和printf)一样可以在程序中直接调用。
rand函数的用法如下:
首先在程序开头预处理命令部分加上#include<stdlib.h>,其中<stdlib.h>是C中的标准库头文件,我们在用rand函数时需要用到这个头文件 [注1]。它的作用是为了对rand()函数进行引用性声明,以便在下面的程序中使用它。这和我们在用到scanf和printf函数时需要在程序开头写上#include<stdio.h>(标准输入/输出头文件)是一样的。
随机函数rand使用的格式为:
A=rand()%x+y;
这条语句的意思是,自动产生一个以y为下限,以x+y为上限的随机数,并把值赋给A。即A为y到x+y之间的随机数。
例如,有语句:
int a;
a=rand()%89+10;
执行该语句后,a即可得到一个10~100之间的整数赋值。
注意区别于:
a=rand()%100;
执行这条语句,a可能取值的上限同样为100,但下限为0,a可以取到10以下的数。相当于:a=rand()%100+0;
下面我们来看一个完整的例子:
[eg.1]输入10个两位数,并把他们的和打印出来。
1.从键盘输入数据:
#include<stdio.h>
void main()
{
int a[10],sum=0;
int i;
printf("请输入10个2位数:\printf函数原型在什么头文件里n");
for(i=0;i<10;i++)
{
scanf("%d",&a[i]);
sum=sum+a[i];
}
printf("\n");
printf("这10个数的和是:%d \n",sum);
}
运行结果:
请输入10个两位数: 14 32 47 61 20 17 55 76 29 10 这10个数的和是:361 |
2.使用随机数:
#include<stdio.h>
#include<stdlib.h>
void main()
{
int a[10],sum=0;
int i;
printf("系统自动生成随机数:\n");
for(i=0;i<10;i++)
{
a[i]=rand()%89+10; /* a从10-99之间取值,即a是两位数 */
printf("%d ",a[i]);
sum=sum+a[i];
}
printf("\n");
printf("这10个两位数的和是:%d \n",sum);
}
运行结果:
系统自动生成随机数: 51 54 25 77 44 70 96 87 94 88 这10个两位数的和是:686 |
经运行比较后可以感觉到,使用随机数可以简化程序运行,方便人的工作。
要是你够细心,再次运行上面这个程序,观察结果,你会发现两次系统产生的随机数的值是
完全相同的。这里你一定会问,这些数字不是随机产生的吗?两次的结果怎么会一样?
实际上,rand函数产生的是伪随机数。当你调用它,它产生的数看上去是随机的,但每次执行这个程序时,这些数的顺序都会重复。这是因为rand()会用系统指定的某个数做为一个种子,而且这个数是每次开机时就指定好的,如果不通过其他方法为rand()重新指定种子,则在下次开机前该种子数都不会变。所以每次出现的随机数是一样的。这种重复性是函数rand的一个重要特点。
如果你希望在程序完成后,每次运行时产生一组不同的随机数,那么就要用到另一个标准库函数:srand函数。这个函数就可以为rand函数指定任意的种子。在生成随机数的过程中需要我们把rand和srand两个函数结合使用,这个过程称为随机化。
使用srand函数,需要由我们给系统提供这个种子,这个种子通常是unsigned(无符号)型。
srand函数使用的格式是:
unsigned seed; /* 定义种子为无符号型变量 */
srand(seed); /* 在下边结合使用rand函数,最终生成一组随机数 */
同样,使用这个函数时需要在程序开头写上#include<stdlib.h>。
[eg.2]使用srand函数对例1进行改进:
#include<stdio.h>
#include<stdlib.h>
void main()
{
int a[10],sum=0;
int i;
unsigned seed;
printf("please enter seed:\n"); /* 提示输入一个数,作为种子 */
scanf("%u",&seed); /* 注意这里%u用来表示无符号数 */
srand(seed); /* 设置随机数生成器的种子 */
printf("系统自动生成随机数:\n");
for(i=0;i<10;i++)
{
a[i]=rand()%89+10;
printf("%d ",a[i]);
sum=sum+a[i];
}
printf("\n");
printf("这10个两位数的和是:%d \n",sum);
}
让我们将这个程序运行几次,并观察其结果。已经可以获得每次不一样的随机数了。
运行结果:
Please enter seed: 156 系统自动生成随机数: 24 51 84 35 24 94 83 22 15 79 这10个两位数的和是:511 |
再次运行:
Please enter seed: 99 系统自动生成随机数: 15 16 37 54 49 39 58 11 32 39 这10个两位数的和是:350 |
但须注意的是,当输入的种子的值确定时,获得的随机数也会相同。
如:再次输入156作为种子,结果如下:
Please enter seed: 156 系统自动生成随机数: 24 51 84 35 24 94 83 22 15 79 这10个两位数的和是:511 |
如果想让系统自动生成种子,而无需手动输入,可以在例2中程序开头加上:#include<time.h>,并把红部分的语句改为:
srand((unsigned)time(NULL));
其中time()为时间函数,包含在<time.h>头文件中 [注2],NULL是参数。这条语句能够在很短的时间内返回计算机的当前时间,并将这个值转换为无符号整数,作为种子。相当于用time(NULL)生成的值替换了例2中的seed.
写出完整的程序后,运行,就能够自动生成不重复的随机数了,并且省去了enter seed的过程。
下面的图可以直观表示srand与rand的关系:
[练习题]1.掷骰子游戏:
每个骰子有6个面,分别为1-6点,每掷一次只有一个点数朝上。使用随机数模拟掷6000次骰子的过程,统计掷出每一面的次数。
2.运气游戏:
游戏的规则是:每个玩家每次一起掷两个骰子,计算面朝上的两个点数之和。如果第一次掷的结果是7或11,那么玩家就获胜。如果第一次掷到2,3或12,玩家就输了,即庄家获胜。如果第一次掷的结果是其他数(4,5,6,8,9,10)那么玩家需要再次掷骰子,直到掷出的点数与这个结果相同,玩家获胜。但是如果再次掷骰子的过程中掷到了7点,玩家输,庄家获胜。
编程序模拟游戏中玩家掷骰子的过程,要求包含各种不同的投掷情况,并判断玩家获胜/失败。
程序结果举例:
玩家投掷点数:5+6=11 玩家获胜! |
玩家投掷点数:4+1=5 点数为5,继续投掷! 玩家投掷点数:3+4=7 玩家失败! |
玩家投掷点数:4+1=5 点数为5,继续投掷! 玩家投掷点数:6+2=8 点数为8,继续投掷! 玩家投掷点数:3+2=5 得到相同点数,玩家获胜! |
习题1为基础题,习题2为提高题,请根据自身情况选择解答。需要习题参考答案请回复。
关于随机数就说这么多,欢迎大家讨论交流。
附:
[注]1.<stdlib.h>,标准库头文件,包含数字转换到文本以及文本转换到数字的函数原型,还有内存分配、随机数字以及其它实用函数的函数原型。
2.<time.h>,标准库头文件,包含时间和日期操作的函数原型和类型。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论