1. 线性同余生成器(Linear Congruential Generator, LCG)
原理: 线性同余生成器是最简单和最古老的伪随机数生成算法之一。它使用线性同余方程来生成一个伪随机数序列。
公式: Xn+1=(aXn+c)mod m
- XXX 是生成的随机数序列。
- aaa 是乘数。
- ccc 是增量。
- mmm 是模数。
C语言实现:
#include <stdio.h>
#define MODULUS 2147483648 // 2^31
#define MULTIPLIER 1103515245
#define INCREMENT 12345
static unsigned long seed = 1; // 初始种子
void srandLCG(unsigned long s) {
seed = s;
}
unsigned long randLCG() {
seed = (MULTIPLIER * seed + INCREMENT) % MODULUS;
return seed;
}
int main() {
srandLCG(123); // 设置种子
for (int i = 0; i < 10; i++) {
printf("%lu\n", randLCG());
}
return 0;
}
2. 梅森旋转算法(Mersenne Twister)
原理: 梅森旋转算法是一种更复杂但质量更好的伪随机数生成算法。它以梅森素数(一个形如2n−12^n-12n−1的素数)为基础,有极长的周期和良好的随机性。
#include <stdio.h>
#define N 624
#define M 397
#define MATRIX_A 0x9908b0dfUL
#define UPPER_MASK 0x80000000UL
#define LOWER_MASK 0x7fffffffUL
static unsigned long mt[N]; // 624个字的状态向量
static int mti = N + 1; // mt[N] + 1 意味着 mt[N] 未初始化
void init_genrand(unsigned long s) {
mt[0] = s & 0xffffffffUL;
for (mti = 1; mti < N; mti++) {
mt[mti] = (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
mt[mti] &= 0xffffffffUL;
}
}
unsigned long genrand_int32(void) {
unsigned long y;
static unsigned long mag01[2] = {0x0UL, MATRIX_A};
if (mti >= N) {
int kk;
if (mti == N + 1)
init_genrand(5489UL); // 默认种子
for (kk = 0; kk < N - M; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
mt[kk] = mt[kk + M] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
for (; kk < N - 1; kk++) {
y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
mt[kk] = mt[kk + (M - N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
}
y = (mt[N - 1] & UPPER_MASK) | (mt[0] & LOWER_MASK);
mt[N - 1] = mt[M - 1] ^ (y >> 1) ^ mag01[y & 0x1UL];
mti = 0;
}
y = mt[mti++];
y ^= (y >> 11);
y ^= (y << 7) & 0x9d2c5680UL;
y ^= (y << 15) & 0xefc60000UL;
y ^= (y >> 18);
return y;
}
int main() {
init_genrand(1234); // 设置种子
for (int i = 0; i < 10; i++) {
printf("%lu\n", genrand_int32());
}
return 0;
}
3. Xorshift 算法
原理: Xorshift 算法是一种高效的伪随机数生成算法,通过对数的位进行异或和移位操作来生成随机数。
C语言实现:
#include <stdio.h>
static unsigned long x = 123456789;
static unsigned long y = 362436069;
static unsigned long z = 521288629;
static unsigned long w = 88675123;
unsigned long xorshift() {
unsigned long t = x ^ (x << 11);
x = y; y = z; z = w;
return w = w ^ (w >> 19) ^ (t ^ (t >> 8));
}
int main() {
for (int i = 0; i < 10; i++) {
printf("%lu\n", xorshift());
}
return 0;
}
以上是几种常见的伪随机数生成算法及其在C语言中的实现。根据具体的应用需求,可以选择合适的PRNG算法来生成随机数。