【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
英文地址,請注明出處:http://en.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用,把的個網口做外部通訊,…