OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 2880|回复: 4

C语言中随机数的生成

[复制链接]

5

主题

30

帖子

0

精华

高级会员

Rank: 4

积分
852
金钱
852
注册时间
2018-10-11
在线时间
69 小时
发表于 2018-11-5 19:54:55 | 显示全部楼层 |阅读模式

       

       
刚好在找这方面的资料,看到了一片不错的,就全文转过来了,省的我以后再找找不到。

在C语言中,可以通过rand函数得到一个“伪随机数”。这个数是一个整数,其值大于等于0且小于等于RAND_MAX。rand函数和常量RAND_MAX都定义在库stdlib.h之中,这意味着必须在头文件中包含库stdlib.h才能使用rand函数和常量RAND_MAX。

rand函数声明为:
int rand(void)

//代码示例 start
#include <stdio.h>
#include <stdlib.h>

int main()
{
    printf("%d %d\n", rand(), rand());
}
//代码示例 end

编译运行以上代码,将在屏幕显示两个随机数。但多次运行这个程序,你会发现每次程序启动后生成的两个随机数都是一样的!可见,rand()生成的值并不随机。
标准库(stdlib)中随机数的一个可能的实现如下:
//代码示例 start
#define RAND_MAX 0x7fff
unsigned long int next = 1;

int rand(void)
{
    next = next * 1103515245 + 12345;
    return (unsigned int)(next/65536) % RAND_MAX;
}

/*srand函数:为rand函数设置种子数*/
void srand(unsigned int seed)
{
    next = seed;
}
//代码示例 end

由上可知,只要我们每次在程序运行开始时用srand设置好不同的nex值,那么程序每次运行都将得到不同是随机序列。那又如何给srand传入不同的数呢?随机数?好吧,这下变成鸡生蛋蛋生鸡的问题了。其实不用那么复杂。我们只需要把当前的时间作为srand的参数传入就好了。程序每次运行的时间点是肯定是不一样的。
要获取当前时间,可以使用time库中的time函数。示例如下:
//代码示例 start
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
    srand((int)time(0));
    printf("%d %d\n", rand(), rand());
}
//代码示例 end

编译运行上述代码,就能让程序每次运行都得到不同的随机值了。

程序中time(0)函数返回值类型为time_t(time_t定义为长整型),time(0)返回从1970年1月1日零时零分零秒到目前为止所经过的时间,单位为秒。

好了,到目前为止,我们已经解决了如何在区间[0, RAND_MAX]内等概率随机获得一个整数的问题。那么又应该如何等概率的随机获取任意范围内的整数呢?其实只需要对rand()函数生成的随机数进行取模运算就可以了。参考下述代码:
    int a = rand() % 100;
    int b = rand() % 20 + 5;
执行上述代码后(当然前面应该调用srand函数),获取的整数a是[0, 100)区间的均匀随机整数;而获取的整数b,则是[5, 25)区间的均匀随机整数了。
但紧接着我们不禁要问了:随机浮点数又该怎么生成呢?其实很简单,用rand()生成的数除以RAND_MAX,不就能得到0~1之间的浮点数了么?而要得到区间[a, b]的浮点数,用这个值扩展一下不就好了?比如 s= rand() / RAND_MAX; s = a + (b-a)* s;这样就能得到我们想要的随机数s了。好的,假如我们要得到区间[3, 5]之间的一个随机浮点数,那么很简单,代码如下:
//代码示例 start
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
    float s;
    srand((int)time(0));
    s = (double)rand() / RAND_MAX;
    s = 3 + (5-3) * s;
    printf("%f\n", s);
}
//代码示例 end
编译运行,好吧。为什么每次程序运行得到的结果都是3.0呢?程序逻辑没有问题的啊?!
在倒数第三行设置断点调试程序,我们会发现,在第一次完成对s的赋值之后,s的值为0.0。反复运行程序进行调试,s的值都是0.0。为什么s的值总是0.0呢?
原来,在C语言中,如果 / 操作符两边都是整数的话,那么运算后的结果也是一个整数,而且是向下取整的整数。即2 / 3得到0,3 / 2得到1。又由于rand()得到的值总是小于RAND_MAX,因此表达式 rand() / RAND_MAX也就只能得到整数0了,整数0在赋值给s时强制转换为浮点数0.0。
为了让 / 操作符进行浮点运算,我们可以将 / 操作符的操作数转化为浮点数。比如:(float)rand() / RAND_MAX;这样,就能得到我们想要的结果了。正确的例子如下:
//代码示例 start
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
    float s;
    srand((int)time(0));
    s = (float)rand() / RAND_MAX;
    s = 3 + (5-3) * s;
    printf("%f\n", s);
}
//代码示例 end




正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

13

主题

640

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1331
金钱
1331
注册时间
2016-8-1
在线时间
229 小时
发表于 2018-11-6 09:23:22 | 显示全部楼层
回复 支持 反对

使用道具 举报

0

主题

28

帖子

0

精华

初级会员

Rank: 2

积分
60
金钱
60
注册时间
2018-11-19
在线时间
2 小时
发表于 2018-11-22 09:42:18 | 显示全部楼层
C语言很难吗?   我想学Java
回复 支持 反对

使用道具 举报

5

主题

30

帖子

0

精华

高级会员

Rank: 4

积分
852
金钱
852
注册时间
2018-10-11
在线时间
69 小时
 楼主| 发表于 2018-11-22 22:16:52 | 显示全部楼层
我先学完C再来java
回复 支持 反对

使用道具 举报

0

主题

28

帖子

0

精华

初级会员

Rank: 2

积分
60
金钱
60
注册时间
2018-11-19
在线时间
2 小时
发表于 2018-12-1 10:06:10 | 显示全部楼层
我是看不懂喽!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-6-16 16:55

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表