| 難點 | 解法 |
| 隨機數重複性 | srand((unsigned)time(NULL)) 以當前時間為種子,每次運行結果不同 |
| 範圍映射 [0, RAND_MAX] → [0, 1000000] | (long long)rand() * 1000000 / (RAND_MAX + 1) 或 rand() % 1000001 (輕微非均勻) |
| 保證第一數 ≤ 第二數 | 生成第二數後 while (b < a) b = rand() % 1000001; 重采樣 |
完整代碼 (健壯版)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_VAL 1000000
int main() {
long T;
printf("請輸入 T: ");
if (scanf("%ld", &T) != 1 || T <= 0) {
printf("輸入無效\n");
return 1;
}
srand((unsigned)time(NULL)); // 種子初始化,僅一次
for (long i = 0; i < T; i++) {
long a = rand() % (MAX_VAL + 1);
long b = rand() % (MAX_VAL + 1);
if (a > b) { long tmp = a; a = b; b = tmp; } // 交換保證 a <= b,比重采樣更高效
printf("%ld %ld\n", a, b);
}
return 0;
}
關鍵改進點對比原帖最佳回答
| 項目 | 原帖代碼 | 本文改進版 | 理由 |
| 主函數 | void main() | int main() | 標準 C 要求返回 int |
| 種子 | srand((unsigned long)time(0)) | srand((unsigned)time(NULL)) | 類型匹配,NULL 更清晰 |
| 行數計算 | t=pow(2,t-1) (錯誤理解需求) | 直接循環 T 次 | 需求為「2*T 個數據,每行 2 個」即 T 行 |
| 範圍映射 | rand()*1000000/RAND_MAX | rand() % (MAX_VAL+1) | 簡潔、無浮點、均勻度可接受 |
| 順序保證 | while(tem2>tem1) 重采樣 | if(a>b) swap | O(1) 確定性,避免理論上無限循環 |
| 類型 | long 混用 | 統一 long (或 long long 防溢出) | 一致性 |
進階:更高質量隨機數 (C11 <random> 不可用,用 POSIX)
/* 若需加密級/高質量,Linux 下可用 */
#include <fcntl.h>
#include <unistd.h>
unsigned int rand_secure() {
unsigned int x;
int fd = open("/dev/urandom", O_RDONLY);
read(fd, &x, sizeof(x));
close(fd);
return x;
}
總結
生成滿足「每行兩數、第一數≤第二數、≤100 萬」的隨機數據,核心在於:一次 srand(time)、rand()% 映射範圍、if(a>b) swap 保證順序**。避免 pow 計算行數、while 重采樣、void main 等非標準寫法,代碼簡潔、標準、高效。
- 上一篇文章: C語言轉義字符 \n 的 ASCII 碼值與換行機制解析
- 下一篇文章: C語言解決「暢通工程」最小生成樹問題:Prim/Kruskal 算法完整實現
Copyright ©
程式碼之家 All Rights Reserved