首页 C语言 随机数
文章
取消

C语言 随机数

此篇博客仍在整理中,内容质量及排版比较一般,还请见谅

实际上,计算机只能为我们提供伪随机数,所谓伪随机数就是按照一定算法模拟产生的,其结果是确定的,是可见的。

计算机产生随机数的过程,是根据一个种子为基准,以某个递推公式推算出来的一系列数,当递推的范围足够大、往复性足够强、又符合正态分布或平均分布时,我们就可以认为这是一个近似的真随机数

随机数

在 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
本文由作者按照 CC BY 4.0 进行授权

C语言 数组

C语言 指针