【C 语言生成指定范围随机数(整数 + 小数):原理、实现与避坑指南】

概述

在 C 语言开发中,生成指定范围的随机数是高频需求(如游戏随机道具、数据模拟、测试用例生成等)。但很多新手会卡在 “范围控制”“随机数重复”“小数生成” 等问题上。本文结合实战场景,从原理到代码详细讲解如何生成 1100、11000 等整数,以及 1.0~1000.0 的小数,并对比多语言思路,帮你彻底掌握随机数生成技巧。


一、先搞懂核心:取模运算(%)的范围控制逻辑

生成随机数的第一步是 “限定基础范围”,这依赖于取模运算的数学性质—— 这也是你之前最关注的点,必须先吃透。

1. 取模运算的本质:余数的范围规则

对于任意整数a(被除数,如 rand () 返回值)和正整数n(除数,如 100、1000),a % n的结果(余数r)必然满足:

0 ≤ r < n

 最小余数是 0:当a是n的整数倍时(如 100%100=02000%1000=0);最大余数是n-1:当a比n的整数倍多n-1时(如 99%100=99999%1000=999)。
2. 结合 rand () 函数:得到 0 开头的基础范围

C 语言的rand()函数默认返回0 ~ RAND_MAX(通常是 32767)的随机整数。结合取模运算:

rand() % 100:余数范围0~99(因为n=1000 ≤ r < 100);rand() % 1000:余数范围0~999(因为n=10000 ≤ r < 1000);以此类推,rand() % n始终得到0 ~ n-1的随机整数。

二、实战 1:生成指定范围的整数随机数(如 1~100 、 1 ~ 1000)

知道了 “取模得 0 开头范围” 后,只需加一步 “偏移”,就能得到任意[min, max]的整数范围。

1. 通用公式推导
  • 目标:生成[min, max](含 min 和 max)的整数。
第一步:算 “范围长度”:len = max - min + 1(确保覆盖所有目标值,如 1~100 的长度是 1001~1000 的长度是 1000);
第二步:取模得基础范围:rand() % len → 得到0 ~ len-1;
第三步:偏移到目标起点:+ min → 把0 ~ len-1变成min ~ max。
  • 最终公式:

int random_int = rand() % (max - min + 1) + min;
2. 场景示例:生成 1~100 、 1 ~ 1000 的整数
#include <stdio.h>
#include <stdlib.h>  // 包含rand()、srand()
#include <time.h>    // 包含time(),用于生成种子int main() {// 关键:初始化随机种子(仅需在程序开头执行1次!)// time(NULL)返回当前系统时间戳(秒级),确保每次运行种子不同srand((unsigned int)time(NULL));// 场景1:生成1~100的随机整数int rand_1_100 = rand() % (100 - 1 + 1) + 1;  // 简化为rand()%100 +1printf("1~100的随机整数:%d\n", rand_1_100);// 场景2:生成1~1000的随机整数int rand_1_1000 = rand() % (1000 - 1 + 1) + 1;  // 简化为rand()%1000 +1printf("1~1000的随机整数:%d\n", rand_1_1000);// 拓展:生成50~200的随机整数int rand_50_200 = rand() % (200 - 50 + 1) + 50;  // len=151,0~150 → 50~200printf("50~200的随机整数:%d\n", rand_50_200);return 0;
}

运行结果(每次不同)

1~100的随机整数:47
1~1000的随机整数:623
50~200的随机整数:129

三、实战 2:生成指定范围的小数随机数(如 1.0~1000.0)

很多新手会误以为 “用 rand ()%1000 再除以 100” 就能生成小数 —— 这是错误的!因为rand()返回整数,取模后仍是整数,直接除法只能得到 “离散小数”(如 1.00、2.00),而非连续小数。

1. 核心思路:整数转浮点数 + 归一化 + 缩放

生成连续小数的本质是:将rand()的0~RAND_MAX整数范围,通过三步映射到目标小数范围[min, max]:

整数转浮点数:(double)rand() → 把0 ~ 32767 转为0.0 ~ 32767.0;

归一化到 0.0 ~ 1.0:/ RAND_MAX → 用浮点数除以RAND_MAX,得到0.0(含)~1.0(含)的均匀小数;

缩放 + 偏移:* (max - min) + min → 先缩放到0.0(max-min),再偏移到minmax。

2. 通用公式与示例代码

通用公式

double random_double = (double)rand() / RAND_MAX * (max - min) + min;

场景示例:生成 1.0~1000.0 的小数

运行
#include <stdio.h>
#include <stdlib.h>
#include <time.h>int main() {srand((unsigned int)time(NULL));  // 初始化种子(仅1次)// 生成1.0~1000.0的随机小数(保留2位小数打印)double rand_1_1000_double = (double)rand() / RAND_MAX * (1000.0 - 1.0) + 1.0;printf("1.0~1000.0的随机小数:%.2f\n", rand_1_1000_double);// 拓展:生成5.5~20.5的随机小数(保留3位小数打印)double rand_5_5_20_5 = (double)rand() / RAND_MAX * (20.5 - 5.5) + 5.5;printf("5.5~20.5的随机小数:%.3f\n", rand_5_5_20_5);return 0;
}

运行结果(每次不同)

1.0~1000.0的随机小数:456.78
5.5~20.5的随机小数:12.345

四、避坑指南:srand () 的 3 个关键注意事项

“用时间戳解决种子问题”,这是正确的,但还有 3 个细节容易踩坑,必须注意:

1. 仅初始化 1 次,不要在循环中反复调用
  • 错误示例(同一秒内种子相同,随机数重复):
for (int i = 0; i < 5; i++) {srand((unsigned int)time(NULL));  // 错误:循环内反复初始化printf("%d ", rand()%100);  // 可能输出5个相同的数(同一秒内time(NULL)不变)
}
  • 正确示例(程序开头初始化 1 次):
运行
srand((unsigned int)time(NULL));  // 正确:仅1次
for (int i = 0; i < 5; i++) {printf("%d ", rand()%100);  // 输出5个不同的数
}
2. 种子类型必须是 unsigned int

time(NULL)返回time_t类型(通常是 signed 整数),而srand()的参数要求是unsigned int,因此必须强制转换:

srand((unsigned int)time(NULL));  // 正确:强制转换为无符号整数
3. 秒级精度不够?用毫秒级种子(进阶)

如果需要 “同一秒内多次运行程序也生成不同随机数”(如高频测试场景),秒级时间戳不够用,可改用毫秒级精度:

Windows:用GetTickCount()(返回开机到现在的毫秒数);
Linux/macOS:用clock_gettime()(支持纳秒级精度)。

Windows 示例:

#include <windows.h>  // 包含GetTickCount()// 初始化毫秒级种子
srand((unsigned int)GetTickCount());

五、多语言对比:C/Java/Python 的随机数思路一致性

Java、Python 思路一样,这一点非常关键 —— 不同语言的随机数生成,核心逻辑完全相通,只是语法不同:

在这里插入图片描述

  • 核心共性:都是 “先得到 0 开头的基础范围,再通过缩放 / 偏移映射到目标范围”,无需关注底层算法,只需掌握范围控制逻辑。

六、常见问题汇总(Q&A)

1, Q:为什么 rand () 生成的随机数每次都一样?
A:没初始化种子(srand ()),或在循环中反复初始化种子。只需在程序开头调用 1 次srand((unsigned int)time(NULL))。
2. Q:用 rand ()%1000 生成 1~1000 的整数,为什么会少了 1000?
A:rand()%1000得到 0~999,需加 1(rand()%1000 +1)才能覆盖 1~1000。
3. ** Q:生成小数时,用 rand ()%100000/100.0 为什么不好?**
A:这是 “离散小数”(步长 0.01,如 1.01、1.02),无法生成 1.005、1.2345 等连续值,不符合多数场景需求。

总结

生成指定范围的随机数,核心是 “取模定长度,偏移定起点”(整数)或 “归一化 + 缩放”(小数),再配合srand()初始化种子避免重复。记住以下 2 个核心公式,无论范围是 1 ~ 100 还是 1 ~ 10000,都能轻松实现:

  • 两种类型实现公式
整数:rand() % (max - min + 1) + min
小数:(double)rand() / RAND_MAX * (max - min) + min
    • Name: LiuJinTao

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

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

相关文章

一个简单的langgraph agent系统

本文基于langgraph的预制件 Agent Chat UI和《搭建一个本地langgraph服务》中的本地服务构建一个简单的agent系统。 说明&#xff1a;Agent Chat UI需要nodejs版本18及以上&#xff0c;而nodejs18需要的glibc版本为2.28&#xff0c;本人使用操作系统为ubuntu18.04&#xff0c;g…

通过SSH来推送本地文件夹到Github

配置SSH git使用SSH配置&#xff0c; 初始需要以下三个步骤 使用秘钥生成工具生成rsa秘钥和公钥 将rsa公钥添加到代码托管平台 将rsa秘钥添加到ssh-agent中&#xff0c;为ssh client指定使用的秘钥文件 具体操作如下&#xff1a; 第一步&#xff1a;检查本地主机是否已经存在…

视频转webp批量处理工具哪个好?这里有答案

你是不是也遇到过这样的困扰&#xff1a;手机里存满了精彩的短视频&#xff0c;想做成动图分享到社交媒体&#xff0c;却发现转换后的GIF文件巨大无比&#xff0c;画质还惨不忍睹&#xff1f;要怎么把手机视频转webp&#xff0c;才能既保持高清画质&#xff0c;又能大幅减小文件…

【Fastjson】Fastjson2 在不同 Modules 模块包下,@JSONField name映射无法反序列化的 BUG 及解决

问题&#xff1a;在使用 alibaba fastjson2 做 JSONField 字段名映射时&#xff0c;在同模块包下 Flink Jar 任务正常映射&#xff0c;本地测试正常映射&#xff0c;但是将两个模块包上传至 Flink Cluster 之后&#xff0c;出现反序列化异常&#xff0c;子模块无法反序列化父模…

Go语言基础---数据类型间的故事

Go语言基础—数据类型间的故事 目录 前言基本数据类型 整形字节特殊整形unsafe.Sizeof数字字面量语法浮点型布尔值字符串byte和rune类型 运算符 算术运算符关系运算符逻辑运算符位运算符赋值运算符 前言 Go语言是Google开发的一种静态强类型、编译型语言。Go语言语法与C相近…

dedecms软件等级★号改成图片图标显示的办法

我们在用到dedecms织梦的软件模型&#xff0c;在调用软件星级的时候&#xff0c;要把默认的星号改为图片&#xff0c;这个要怎么操作呢&#xff1f;1、软件模型管理里面-字段管理-字段配置softrankislink一行改为&#xff1a;<field:softrank itemname软件等级 typeint isnu…

windows下安装claude code+国产大模型glm4.5接入(无需科学上网)

下载安装node.js https://nodejs.org/en/download 安装版.msi 直接下载安装即可 免安装版.zip 1.解压下载的压缩包 2.创建数据缓存存储目录cache和全局安装工具目录global 3.配置环境变量 【我的电脑】右键选中【属性】-> 找到【高级系统设置】-> 右下角【环境变量…

嵌入式 - ARM4

裸机实现LED闪烁一、启动代码1. 异常向量表配置1. .global汇编器指令&#xff0c;全局定义标签_start&#xff0c;作为汇编程序的默认起点2. 配置标签配置标签时可以前置加_ &#xff0c;以便和普通标签或系统标签做区分3. 异常向量表ARM架构规定异常向量表位置固定&#xff0c…

《C++ 108好库》之2 多线程库thread,mutex,condition_variable,this_thread

《C 108好库》之之2 多线程库thread&#xff0c;mutex&#xff0c;condition_variable&#xff0c;this_thread《C 108好库》之2 多线程库thread&#xff0c;mutex&#xff0c;condition_variable&#xff0c;this_threadstd::thread类​​互斥量&#xff08;Mutex&#xff09;…

Android系统框架知识系列(二十):专题延伸:JVM vs ART/Dalvik - Android运行时演进深度解析

​关键词​&#xff1a;运行时优化、AOT编译、JIT编译、内存管理、电池效率、性能分析一、Android运行时演进背景1. 移动环境的特殊挑战Android运行时环境的演进源于移动设备的独特限制&#xff1a;​移动设备约束条件​&#xff1a;​有限的内存资源​&#xff1a;早期设备仅1…

ubuntu 22 安装轻量级桌面Xfce并使用xrdp远程桌面连接

1.安装Xfce:sudo apt install xubuntu-desktop -y2.安装xrdp:sudo apt install xrdp -y3.配置xrdp&#xff0c;nano /etc/xrdp/xrdp.ini:[Globals] ... port3389 ; 远程连接端口&#xff0c;默认是3389&#xff0c;可以改成自己喜欢的端口... ; ; Session types ;; Some sess…

【Flask】测试平台开发,数据看板开发-第二十一篇

概述&#xff1a;在前面我们已经实现了我们的产品创建管理&#xff0c;应用管理管理&#xff0c;需求提测管理但是每周提测了多少需求&#xff0c;创建了哪些产品&#xff0c;我们是不是看着不是很直观&#xff0c;接下来我们就需要开发一个数据看板功能&#xff0c;实现能够看…

我是程序员,不是程序猿:请别把我当猴耍——拒绝被低估,用专业赢得尊重

摘要 本文旨在深度剖析“程序员”与“程序猿”一字之差背后所反映的职业尊严与身份认同问题。我们生活在一个技术驱动的时代&#xff0c;但对技术创造者的认知却常常被“程序猿”、“码农”等标签简单化、甚至矮化。本文将从正名开始&#xff0c;辨析“程序员”的专业内涵&…

C++中vector删除操作的安全隐患与最佳实践

std::vector 是C标准模板库&#xff08;STL&#xff09;中最常用的动态数组容器&#xff0c;提供了高效的随机访问和动态扩容能力。然而&#xff0c;其删除操作如果使用不当&#xff0c;会引入严重的安全隐患&#xff0c;包括未定义行为、内存泄漏和数据竞争等问题。本文将深入…

Unix/Linux 系统中的 `writev` 系统调用

<摘要> 本文对 Unix/Linux 系统中的 writev 系统调用进行了全面深入的解析。内容涵盖了其产生的背景&#xff08;从传统 write 的局限性到分散/聚集 I/O 概念的引入&#xff09;、核心概念&#xff08;如 struct iovec、系统调用流程&#xff09;。重点剖析了其设计意图&…

深入理解 Android targetSdkVersion:从 Google Play 政策到依赖冲突

深入理解 Android targetSdkVersion&#xff1a;从 Google Play 政策到依赖冲突 作为 Android 开发者&#xff0c;你很可能在 Android Studio 中见过这条提示&#xff1a;Google Play requires that apps target API level 33 or higher。它像一个尽职的提醒者&#xff0c;时常…

灰匣(GrayBox)1.0.0 发布【提升系统权限APP】

灰匣是一个提升系统权限的工具&#xff0c;可以配合Root、三方软件&#xff08;Shizuku&#xff09;以及【设备管理员】&#xff08;设备所有者&#xff09;实现一些高级功能及底层接口&#xff0c;可以自动隔离&#xff08;冻结/禁用&#xff09;不必要的应用&#xff0c;如某…

PAT 1104 Sum of Number Segments

这一题的大意就是找一个数组中的所有子数组&#xff0c;它们的累加和为多少&#xff0c; 题目上给出的数据范围是O(n^5)那么只能遍历一次&#xff0c;不能用暴力的方法求出。 看到这一题我有两个思路&#xff1a; 1.试图用双指针和滑动窗口来把O&#xff08;n^2)的时间复杂度降…

[万字长文]AJAX入门-常用请求方法和数据提交、HTTP协议-报文、接口文档、案例实战

本系列可作为前端学习系列的笔记&#xff0c;代码的运行环境是在VS code中&#xff0c;小编会将代码复制下来&#xff0c;大家复制下来就可以练习了&#xff0c;方便大家学习。 HTML、CSS、JavaScript系列文章 已经收录在前端专栏&#xff0c;有需要的宝宝们可以点击前端专栏查…

Codesy中的UDP发送信息

Codesy UDP通讯 概述 CAA Net Base Services UDP通讯的建立 发送UDP 状态控制 效果 概述 Codesys中默认安装的通讯支持很多,不安装其他的软件也可以实现TCP通讯。但是,在使用UDP通讯时,因为我们的PLC有两个网卡,一般我们把第一个网口做编程和HMI用,把的个网口做外部通讯,…