C语言rand和srand用法详解

news2024/11/26 10:30:57

在实际编程中,我们经常需要生成随机数,例如,贪吃蛇游戏中在随机的位置出现食物,扑克牌游戏中随机发牌。

在C语言中,我们一般使用 <stdlib.h> 头文件中的 rand() 函数来生成随机数,它的用法为:

int rand (void);

void 表示不需要传递参数。

C语言中还有一个 random() 函数可以获取随机数,但是 random() 不是标准函数,不能在 VC/VS 等编译器通过,所以比较少用。

rand() 会随机生成一个位于 0 ~ RAND_MAX 之间的整数。

RAND_MAX 是 <stdlib.h> 头文件中的一个宏,它用来指明 rand() 所能返回的随机数的最大值。C语言标准并没有规定 RAND_MAX 的具体数值,只是规定它的值至少为 32767。在实际编程中,我们也不需要知道 RAND_MAX 的具体值,把它当做一个很大的数来对待即可。

下面是一个随机数生成的实例:

#include<stdio.h>
#include<stdlib.h>
intmain(){
int a =rand();
printf("%d\n",a);
return0;
}

运行结果举例:

193

随机数的本质

多次运行上面的代码,你会发现每次产生的随机数都一样,这是怎么回事呢?为什么随机数并不随机呢?

实际上,rand() 函数产生的随机数是伪随机数,是根据一个数值按照某个公式推算出来的,这个数值我们称之为“种子”。种子和随机数之间的关系是一种正态分布,如下图所示:

种子在每次启动计算机时是随机的,但是一旦计算机启动以后它就不再变化了;也就是说,每次启动计算机以后,种子就是定值了,所以根据公式推算出来的结果(也就是生成的随机数)就是固定的。

重新播种

我们可以通过 srand() 函数来重新“播种”,这样种子就会发生改变。srand() 的用法为:

void srand (unsigned int seed);

它需要一个 unsigned int 类型的参数。在实际开发中,我们可以用时间作为参数,只要每次播种的时间不同,那么生成的种子就不同,最终的随机数也就不同。

使用 <time.h> 头文件中的 time() 函数即可得到当前的时间(精确到秒),就像下面这样:

srand((unsigned)time(NULL));

对上面的代码进行修改,生成随机数之前先进行播种:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
intmain(){
int a;
srand((unsigned)time(NULL));
    a =rand();
printf("%d\n", a);
return0;
}

多次运行程序,会发现每次生成的随机数都不一样了。但是,这些随机数会有逐渐增大或者逐渐减小的趋势,这是因为我们以时间为种子,时间是逐渐增大的,结合上面的正态分布图,很容易推断出随机数也会逐渐增大或者减小。

生成一定范围内的随机数

在实际开发中,我们往往需要一定范围内的随机数,过大或者过小都不符合要求,那么,如何产生一定范围的随机数呢?我们可以利用取模的方法:

int a = rand() % 10; //产生0~9的随机数,注意10会被整除

如果要规定上下限:

int a = rand() % 51 + 13; //产生13~63的随机数

分析:取模即取余,rand()%51+13我们可以看成两部分:rand()%51是产生 0~50 的随机数,后面+13保证 a 最小只能是 13,最大就是 50+13=63。

最后给出产生 13~63 范围内随机数的完整代码:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
intmain(){
int a;
srand((unsigned)time(NULL));
    a =rand()%51+13;
printf("%d\n",a);
return0;
}

连续生成随机数

有时候我们需要一组随机数(多个随机数),该怎么生成呢?很容易想到的一种解决方案是使用循环,每次循环都重新播种,请看下面的代码:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
intmain(){
int a, i;
//使用for循环生成10个随机数
for(i =0; i <10; i++){
srand((unsigned)time(NULL));
        a =rand();
printf("%d ", a);
}

return0;
}

运行结果举例:

8 8 8 8 8 8 8 8 8 8

运行结果非常奇怪,每次循环我们都重新播种了呀,为什么生成的随机数都一样呢?

这是因为,for 循环运行速度非常快,在一秒之内就运行完成了,而 time() 函数得到的时间只能精确到秒,所以每次循环得到的时间都是一样的,这样一来,种子也就是一样的,随机数也就一样了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/336376.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis的事务和锁以及在SpringBoot中的使用

文章目录1、事务2、监视锁3、分布式锁1、事务 Redis中事务的操作主要有三个&#xff1a; # 1、开启事务 # 定事务的开启位置&#xff0c;此指令执行后&#xff0c;后续的所有指令均加入到事务中 1、multi # 2、执行事务 # 设定事务的结束位置&#xff0c;同时执行事务。与mul…

【java】map集合遍历: entrySet()、单独遍历key或者value、 keySet()、iterator遍历

目录 1.增强for循环。利用Map 的 entrySet&#xff08;&#xff09;方法获取元素2.增强for循环。单独遍历key或者value3.增强for循环。利用Map 的 keySet() 方法获取元素4.使用iterator遍历文中实体的定义在上篇笔记中&#xff1a;https://blog.csdn.net/qq_43622777/article/d…

spring面试题 一

一、为了降低Java开发的复杂性&#xff0c;Spring采取了那4种关键策略 基于POJO的轻量级和最小侵入性编程&#xff1b; 通过依赖注入和面向接口实现松耦合&#xff1b; 基于切面和惯例进行声明式编程&#xff1b; 通过切面和模板减少样板式代码。 二、Spring框架的核心&am…

14条生产环境项目踩坑复盘

缓存需要等事务结束之后再删除&#xff0c;避免旧数据导致数据库和缓存不一致。说明&#xff1a;比如线程A在减少账户的余额(11->10)&#xff0c;执行了数据库更新&#xff0c;但是事务还未提交&#xff0c;但把缓存删除了。线程B从缓存里去获取账户的余额&#xff0c;缓存里…

Python Numpy基础教程

本文是一个关于Python numpy的基础学习教程&#xff0c;其中&#xff0c;Python版本为Python 3.x 什么是Numpy Numpy Numerical Python&#xff0c;它是Python中科学计算的核心库&#xff0c;可以高效的处理多维数组的计算。并且&#xff0c;因为它的许多底层函数是用C语言编…

TC358775XBG替代方案|完美替代 TC358775XBG替代方案|低BOM成本DSI转LVDS方案CS5518

TC358775XBG替代方案|完美替代 TC358775XBG替代方案|低BOM成本DSI转LVDS方案CS5518 TC358775XBG芯片的主要功能是DSI到LVDS桥&#xff0c;通过DSI链路实现视频流输出&#xff0c;以驱动LVDS兼容的显示面板。该芯片支持单链路LVDS高达1366768 24位像素分辨率&#xff0c;双链路L…

了解webpack

文章目录一、webpack是什么&#xff1f;二、为什么要使用webpack三、webpack的五个核心概念四、安装webpack提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、webpack是什么&#xff1f; 本质上&#xff0c;webpack 是一个用于现代 JavaScript 应用程…

PyTorch学习笔记:nn.MSELoss——MSE损失

PyTorch学习笔记&#xff1a;nn.MSELoss——MSE损失 torch.nn.MSELoss(size_average None&#xff0c;reduce None&#xff0c;reduction mean)功能&#xff1a;创建一个平方误差(MSE)损失函数&#xff0c;又称为L2损失&#xff1a; l(x,y)L{l1,…,lN}T,ln(xn−yn)2l(x,y)L…

设计模式:建造者模式教你创建复杂对象

一、问题场景 当我们需要创建资源池配置对象的时候&#xff0c;资源池配置类里面有以下成员变量: 如果我们使用new关键字调用构造函数&#xff0c;构造函数参数列表就会太长。 如果我们使用set方法设置字段值&#xff0c;那minIdle<maxIdle<maxTotal的约束逻辑就没地方…

【计组】内存和总线

课程链接&#xff1a;深入浅出计算机组成原理_组成原理_计算机基础-极客时间 一、虚拟内存和内存保护 日常使用的操作系统下&#xff0c;程序不能直接访问物理内存。内存需要被分成固定大小的页&#xff08;Page&#xff09;&#xff0c;再通过虚拟内存地址&#xff08;Virtu…

如何创建一个有效的FAQ/常见问题解答页面?

如果您的网站上没有常见问题解答页面&#xff0c;那么您将错过本可以节省的数小时的销售和支持时间&#xff0c;以及本可以推动购买的新客户。尽管与登录页面或销售页面不同&#xff0c;常见问题解答页面显然不会显示直接的投资回报&#xff0c;但它可以在其他因素上节省您的团…

内网渗透(十五)之内网信息收集-域环境中定位域管理员

系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内网渗透(五)之基础知识-Active Directory活动目录介绍和使用 内网渗透(六)之基…

多路查找树

1.二叉树与 B 树 1.1二叉树的问题分析 二叉树的操作效率较高&#xff0c;但是也存在问题, 请看下面的二叉树 二叉树需要加载到内存的&#xff0c;如果二叉树的节点少&#xff0c;没有什么问题&#xff0c;但是如果二叉树的节点很多(比如 1 亿)&#xff0c; 就 存在如下问题:问…

洞察:2022年医疗行业数据安全回顾及2023年展望

过去的2022年&#xff0c;统筹安全与发展&#xff0c;在医疗信息化发展道路中&#xff0c;数据安全不可或缺。这一年&#xff0c;实施五年多的《网络安全法》迎来首次修改&#xff0c;《数据安全法》、《个人信息保护法》实施一周年&#xff0c;配套的《数据出境安全评估办法》…

用户标签体系建设

一、什么是标签体系 通过给每个用户打标&#xff0c;方便后续通过用户标签来快速筛选用户&#xff0c;给不同的用户满足不一样的需求。 标签体系也能给不同的用户标签群体&#xff0c;推送不同的内容&#xff0c;从而达到精准营销的目的。 二、标签体系实施架构 标签体系架…

盾王电力防护、森林防火预警应急广播方案

适用场景&#xff1a;针对普通路人与进入有涉电危险的区域人员作区别预警&#xff1b;三重音频、广告牌子宣传、LED显示、视频监控、预警干预。主要功能 第一重预警&#xff1a;对岸边上的行人&#xff0c;当你进入有涉电危险的警戒12米范围内。人体感应器探测到会马上发出语音…

光纤、光模块、光纤交换机、光模块组网设计与案例

光纤组网已是当今智能化弱电行业里一种常见的组网方式&#xff0c;组建远距离无线、监控网络时&#xff0c;往往需要使用光纤进行连接通信&#xff0c;使用光纤收发器是经济适用型做法&#xff0c;尤其是在室外的使用。其实光纤收发器不仅可以成对使用&#xff0c;还可以配合光…

ESP-IDF:在客户端网页上实现拍照按钮功能,并跳转新页面显示图片

ESP-IDF:在客户网页上实现拍照按钮功能&#xff0c;并跳转新页面显示图片 核心代码&#xff1a; /* Send response with custom headers and body set as the* string passed in user context*/ //const char* resp_str (const char*) req->user_ctx; const char *resp_s…

MASA Stack 1.0 发布会讲稿——实践篇

MASA Stack 1.0 实践篇 产品智能化 产品智能化的改造怎么做&#xff1f; 我们以采用运营商网络场景的物联网架构举例&#xff0c;如图从左到右&#xff0c;在设备端我们研发了一款净水行业通用的物联网盒子&#xff0c;它带有各种传感器&#xff0c;如TDS、温度、流量、漏水检…

80%的代码AI帮你写?还没这么夸张,不过也快了

兔年春节一过&#xff0c;APIcat进入到云服务版本的开发阶段&#xff0c;过年前发生了一件大事&#xff0c;Chatgpt横空出世&#xff0c;不少人预测Chatgpt会替代的10大行业&#xff0c;其中就有程序员。 这时&#xff0c;一位特斯拉的老哥出来说&#xff0c;GitHub Copilot帮…