C++ 提供了一組函數以生成和使用隨機數字。隨機數字就是從一組可能的值中進行隨機選擇而獲得的一個值。該組中的值都有相同的被選中的幾率。
隨機數字常用於許多不同類型的程序中,以下是一些示例:
- 計算機游戲通常要使用隨機數字來模擬一些隨機過程,例如擲骰子或發牌。
- 模擬程序使用隨機數字來決定后續將要發生的一系列操作或人與動物等的行為。可以創建使用隨機數字的公式以確定特定事件在程序中出現的時間。
- 數據分析程序可能會使用隨機數字隨機選擇要檢驗的數據。
- 計算機安全系統使用隨機數字來加密敏感數據。
C++ 庫有一個名為 rand() 的函數,每次調用該函數都將返回一個非負整數。要使用 rand() 函數,必須在程序中包含 <cstdlib> 頭文件。以下是其用法示例:
randomNum = rand();
但是,該函數返回的數字其實是偽隨機數。這意味着它們具有隨機數的表現和屬性,但實際上並不是隨機的,它們實際上是用算法生成的。
該算法需要一個起始值,稱為種子,以生成數字。如果沒有給出一個種子,那么它將在每次運行時產生相同的數字流。下面的程序說明了這一點:
- //This program demonstrates what happens in C++ if you
- // try to generate random numbers without setting a "seed".
- #include <iostream>
- #include <cstdlib>// Header file needed to use rand
- using namespace std;
- int main()
- {
- // Generate and printthree random numbers
- cout << rand() << " ";
- cout << rand() << " ";
- cout << rand() << endl ;
- return 0;
- }
第1次運行輸出結果:
41 18467 : 6334
第2次運行輸出結果:
41 18467 6334
要在每次運行程序時獲得不同的隨機數字流,則必須為隨機數生成器提供一個種子以開始。在 C++ 中,這是通過調用 srand 函數完成的。
在 rand 被調用之前,srand 函數要先被調用,並且 srand 在整個程序中僅被調用一次。
- // This program demonstrates using random numbers when a
- // "seed" is provided for the random number generator.
- #include <iostream>
- #include <cstdlib> // Header file needed to use srand and rand
- using namespace std;
- int main()
- {
- unsigned seed; // Random generator seed
- // Get a nseed" value from the user
- cout << "Enter a seed value: ";
- cin >> seed;
- // Set the random generator seed before calling rand()
- srand(seed);
- //Now generate and print three random numbers
- cout << rand() << " ";
- cout << rand() << " ";
- cout << rand() << endl;
- return 0;
- }
第1次運行結果:
Enter a seed value: 19
100 15331 - 209
第2次運行結果:
Enter a seed value: 171
597 10689 28587
程序中,第 9 行中創建的用於保存種子的變量 seed 被聲明為 unsigned 無符號類型。這個數據類型只保存非負整數。這是 srand 函數在調用時期望接收的數據類型,因此使用 unsigned 變量類型可以保證不會將負數發送給 srand。從程序的輸出可以看出,每次程序使用不同的種子運行時,都會生成不同的隨機數字流。然而,如果再次使用 19 或 171 作為種子運行程序,則將獲得與第一次完全相同的數字。
程序的第 12 行中,使用 cin 從用戶的輸入獲取隨機數生成器種子的值。實際上,獲取種子值的另一個常見做法是調用 time 函數,它是 C++ 標准庫的一部分。
time 函數返回從 1970 年 1 月 1 日午夜開始到現在逝去的秒數,因此每次運行程序時,它都將提供不同的種子值。下面程序演示了 time 函數的用法。請注意,在調用它時必須給它傳遞一個參數 0。同時程序中包含一個新的頭文件 ctime,此頭文件是使用 time 函數所必需的。
- //This program demonstrates using the C++ time function
- //to provide a nseed,T for the random number generator.
- #include <iostream>
- #include <cstdlib> // Header file needed to use srand and rand
- #include <ctime> // Header file needed to use time
- using namespace std;
- int main()
- {
- unsigned seed; // Random generator seed
- // Use the time function to get a "seed” value for srand
- seed = time(0);
- srand(seed);
- // Now generate and print three random numbers
- cout << rand() << " " ;
- cout << rand() << " " ;
- cout << rand() << endl;
- return 0;
- }
程序輸出結果:
2961 21716 181
限制隨機數的范圍
有時程序需要一個特定范圍內的隨機數。要將隨機數的范圍限制在 1 和某個最大值 max 之間的整數,可以使用以下公式:
number = rand() % max + 1;
例如,要生成 1〜6 的隨機數來代表骰子的點數,則可以使用以下語句:
dice = rand() % 6 + 1;
這里簡單介紹一下其工作原理。求余數運算符(%)可以獲得整除之后的余數。當使用通過 rand 函數返回的正整數除以6時,余數將是 0〜5 的數字。因為目標是 1〜6 的數字,所以只需要給余數加 1 即可。
這個想法可以擴展到任意范圍內的隨機數,其通用公式如下:
number = (rand()%(maxValue - minValue +1)) + minValue;
在上述公式中,minValue 是范圍內的最小值,而 maxValue 則是范圍內的最大值。例如,要獲得 10〜18 的隨機數,可以使用以下代碼給變量 number 賦值:
const int MIN_VALUE = 10;
const int MAX_VALUE = 18;
number = rand() % (MAX_VALUE - MIN_VALUE + 1) + MIN_VALUE;
在上述代碼中,(MAX_VALUE - MIN_VALUE + 1)的值為 9,這是目標范圍內整數的個數。余數運算符(%)返回的值是 0〜8 的數字,再用它加上 MIN_VALUE(也就是 10),即可獲得 10〜18 的隨機數。