实际上,计算机只能为我们提供伪随机数
,所谓伪随机数
就是按照一定算法模拟产生的,其结果是确定的,是可见的。
计算机产生随机数的过程,是根据一个种子为基准,以某个递推公式推算出来的一系列数,当递推的范围足够大、往复性足够强、又符合正态分布或平均分布时,我们就可以认为这是一个近似的真随机数。
随机数
在 C 语言中,我们可以使用 stdlib.h 提供的 srand()、rand() 两个函数来生成随机数:
void srand(unsigned int seed)
:设置随机数种子,默认为 1。一个标准的做法是将time(0)
作为种子。int rand()
:生成一个随机数,返回值的范围为[0, RAND_MAX]
。如果需要指定范围的随机数,可以利用%
取余运算。
所谓种子可以看作随机数序列的名字,一个种子对应一串随机数序列
,当种子不变时,就会按照随机数序列依次输出随机数。
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <stdlib.h>
int main(){
int i;
for(i=0; i<10; i++){
printf("%d\n", rand());
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ gcc a.c
$ ./a.out
1804289383
846930886
1681692777
1714636915
1957747793
424238335
719885386
1649760492
596516649
1189641421
$ ./a.out
1804289383
846930886
1681692777
1714636915
1957747793
424238335
719885386
1649760492
596516649
1189641421
设置种子
srand()
函数用于设置种子,种子必须是一个unsigned int
无符号整型数值。
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <stdlib.h>
int main(){
int i;
srand(10);
for(i=0; i<10; i++){
printf("%d\n", rand());
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
$ gcc a.c
$ ./a.out
1215069295
1311962008
1086128678
385788725
1753820418
394002377
1255532675
906573271
54404747
679162307
可以发现,要想有随机效果,种子必须不同
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(){
int i;
srand(time(NULL)); // 以当前的时间为种子,time(NULL)返回自1970-01-01 00:00:00到现在经过的秒数
for(i=0; i<10; i++){
printf("%d\n", rand());
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$ gcc a.c
$ ./a.out
755659272
918696383
1713099657
910474541
458968796
1562218559
1956314424
1331007040
316575616
708425496
$ ./a.out
459856438
1815399079
224249789
1607706283
328815573
2046924047
1669414821
904580298
985276193
1977635311
$ ./a.out
150856145
546472499
870233700
1215991304
1250685114
1442271952
291226543
452263359
560933092
1079063603
套用两次运算,让随机序列之间的差异更明显
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(){
int i;
srand(time(NULL));
srand(rand() * rand());
for(i=0; i<10; i++){
printf("%d\n", rand());
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ gcc a.c
$ ./a.out
1170207345
363934337
411175658
140900928
1727039420
1508971834
2103549883
1663524748
1111330508
1720806146
$ ./a.out
2118351144
1741386816
1854616703
2110552475
593903520
2026527922
1809913760
1523501166
824123056
209918970
指定范围
获取指定范围[min, max)
的伪随机数的最简单方式为:(rand() % (max - min)) + min
。例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int nextRand(int beg, int end) {
return (rand() % (end - beg)) + beg;
}
int main(void) {
srand(time(NULL));
srand(rand() * rand());
// 随机一位数 [0, 9]
for (int i = 0; i < 10; i++)
printf("%d, ", nextRand(0, 10));
printf("\b\b \n");
// 随机二位数 [10, 99]
for (int i = 0; i < 10; i++)
printf("%d, ", nextRand(10, 100));
printf("\b\b \n");
// 随机月份值 [1, 12]
for (int i = 0; i < 10; i++)
printf("%d, ", nextRand(1, 13));
printf("\b\b \n");
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ gcc -o main main.c
$ ./main
7, 0, 7, 8, 6, 2, 3, 4, 6, 6
65, 48, 67, 40, 77, 49, 46, 90, 84, 88
1, 6, 2, 12, 12, 12, 1, 6, 5, 4
$ ./main
2, 1, 6, 6, 4, 3, 5, 0, 4, 8
80, 34, 46, 95, 91, 34, 73, 33, 44, 18
9, 6, 12, 4, 8, 3, 3, 9, 1, 5
$ ./main
5, 0, 5, 9, 3, 4, 3, 7, 6, 8
10, 84, 25, 90, 71, 66, 31, 58, 24, 92
4, 5, 12, 6, 9, 7, 4, 6, 8, 5
$ ./main
4, 7, 3, 9, 2, 1, 7, 4, 3, 6
22, 30, 54, 25, 84, 47, 20, 79, 22, 27
5, 12, 12, 1, 6, 2, 8, 3, 12, 9
$ ./main
2, 5, 9, 3, 3, 3, 1, 5, 9, 0
36, 14, 10, 84, 68, 35, 77, 86, 62, 59
7, 6, 8, 10, 1, 4, 2, 8, 11, 3