当前位置: 首页 > news >正文

C语言—如何生成随机数+原理详细分析

如何生成随机数+原理详细分析

  • 前言
  • 一、理解真正生成随机数原理
  • 二、生成指定位数随机数:
    • 1、生成两位随机数:
    • 2、生成三位随机数:


前言

在计算机编程中,随机数的生成是一个常见但极其重要的话题。无论是游戏开发、密码学、模拟仿真,还是简单的抽奖程序,随机数都扮演着关键角色。然而,计算机本身是确定性的机器,它无法真正产生“随机”的数字。因此,我们通常使用**伪随机数生成器(PRNG, Pseudo-Random Number Generator)**来模拟随机性。

C语言提供了 rand()srand() 等函数来生成伪随机数,但其底层原理是什么?如何优化随机数的分布?如何避免常见的陷阱(如种子固定导致随机数可预测)?

本文将深入探讨:

  1. 伪随机数生成的基本原理
  2. C语言中的随机数生成方法(rand()srand()
  3. 如何生成更均匀、更安全的随机数
  4. 现代随机数生成方法的改进(如 C11 的 arc4random()

通过本文,你不仅能学会如何在 C 语言中生成随机数,还能理解其背后的机制,避免在实际应用中遇到潜在问题。
现在,让我们从最基础的 rand() 函数开始,逐步揭开随机数生成的神秘面纱!


一、理解真正生成随机数原理

在这里插入图片描述
这里的第一句说到rand函数会返回一个从0到RAND_MAX的整型,那RAND_MAX的值是多少呢,我们可以将它复制到编译器中然后选中它右击鼠标点击转到定义,就可以看到这句话
在这里插入图片描述
其实RAND_MAX的值也就是0x7fff,转换为十进制也就是32767,所以说rand函数可以随机生成一个0到32767的整型,当你在编译器中尝试时,你会看到:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>int main()
{int n = 10;while (n){int ret = rand();printf("%d\n", ret);n--;}return 0;
}

在这里插入图片描述
当你天真的以为你已经成功的可以生成随机数的时候,你会发现当年再次运行该代码时,它生成的还是这些随机数,也就是第一次运行代码时代码生成了随机数,且每次运行时会生成相同的随机数。
这时我们应该想起对rand函数的描述中还有第二句话:在调用rand函数之前,我们要使用srand函数设置生成随机数的起点。我们又查srand函数:
在这里插入图片描述
我们可以看到srand函数的参数是一个无符号整型并且无返回值,那么这时我们可以来测试一下,就随便给一个无符号整型传给srand函数。
在这里插入图片描述
但是当我们再次执行程序时照样还是这些随机数,当我们把传入srand函数的改变时,发现所给随机数便改变了:
在这里插入图片描述

所以我们只要在每次执行程序的时候给srand函数传入一个与上一次不同的数即可,但是我们就是要生成一个随机数,现在又需要一个随机数,这不成死循环了吗?
这时我们想到在电脑上有一个东西是时刻在发生着变化的,那就是时间,这时我们需要介绍一个概念,那就是时间戳。
时间戳: 当前时间与计算机起始时间的差值,单位是秒。
计算机的起始时间:1970-01-01 08:00:00
在这里插入图片描述
每一秒的时间戳都不一样,所以我们只要把时间戳传入srand函数即可,这时我们就需要用到time函数,因为time函数的返回值就是时间戳。
在这里插入图片描述
这里我们可以看到time函数的参数是time_t型指针,返回值是time_t型,这里的time_t我们也可以把它放到编译器中右击鼠标,点击转到定义:
在这里插入图片描述
这里我们可以看到,其实time_t就是int型被typedef重定义了(也就是起了个别名)而已。
而我们也不需要向time函数传入什么指针,于是我们就向time函数传入一个空指针( NULL)即可,也就是time( NULL),但是srand函数的参数是unsigned int型,所以我们如果要将time函数的返回值传入srand函数,那么我们就需要将time函数的返回值强制性转化会unsigned int型,也就是( unsigned int )time( NULL),所以我们最终将代码写为:
在这里插入图片描述
这样,每次运行代码时所得到的就是真正意义上的随机数了。
如何生成规定位数的随机数:

二、生成指定位数随机数:

1、生成两位随机数:

我们只需要将所得随机数对90取余数,那么我们得到的数就是0-89的数字,这时再加上10便是10-99的数字了。
在这里插入图片描述

2、生成三位随机数:

在这里插入图片描述

查询函数网站:戳

http://www.lryc.cn/news/592739.html

相关文章:

  • 系统IO对于目录的操作
  • 服务器内存满了怎么清理缓存?
  • 多线程-4-线程池
  • 从零构建监控系统:先“完美设计”还是先“敏捷迭代”?
  • 内存数据库的持久化与恢复策略:数据安全性与重启速度的平衡点
  • 数据结构-3(双向链表、循环链表、栈、队列)
  • SGLang 推理框架核心组件解析:请求、内存与缓存的协同工作
  • 【PTA数据结构 | C语言版】左堆的合并操作
  • LS-DYNA分析任务耗时长,如何避免资源浪费与排队?
  • Machine Learning HW2 report:语音辨识(Hongyi Lee)
  • Glary Utilities(系统优化工具) v6.20.0.24 专业便携版
  • 【Python】一些PEP提案(三):with 语句、yield from、虚拟环境
  • [FDBUS4.2] watcher的使用
  • 利用五边形几何关系计算cos36°及推导黄金比例
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | NotesApp(便签笔记组件)
  • 深入理解 Spring:事务管理与事件机制全解析
  • 如何将本地Git仓库推送到远程仓库的一个文件中并保留Commit记录
  • 借助AI学习开源代码git0.7之三git-init-db
  • RoboBrain 2.0(具身智能论文阅读)
  • Deep Multi-scale Convolutional Neural Network for Dynamic Scene Deblurring 论文阅读
  • Visual Studio C++编译器优化等级详解:配置、原理与编码实践
  • 【iOS】消息传递和消息转发
  • gitlab-runner配置问题记录
  • 洞见AI时代数据底座的思考——YashanDB亮相2025可信数据库发展大会
  • 【C++】——类和对象(中)——默认成员函数
  • LVS(Linux Virtual Server)详细笔记(实战篇)
  • 怎么判断一个对象是不是vue的实例
  • 前端自动化测试:Jest、Puppeteer
  • Rust交叉编译自动化实战
  • 车载监控录像系统:智能安全驾驶的守护者