喜迎
春节

Xorshift算法详解:高效伪随机数生成的利器


Xorshift算法是一种快速、轻量级的伪随机数生成器,由George Marsaglia于2003年提出。它以极少的计算量生成高质量的随机数序列,广泛应用于游戏开发、模拟和需要高性能随机数生成的场景。

一、算法核心原理

1. 基本思想

Xorshift基于线性反馈移位寄存器(LFSR)的变体,通过位移(shift)和异或(XOR)操作来改变内部状态。

2. 数学表示

对于32位版本,典型操作为:

1
2
3
x ^= x << a
x ^= x >> b
x ^= x << c

其中 a, b, c 是精心选择的常数。

二、完整算法实现

1. 不同位宽的Xorshift实现

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
<?php

/**
* Xorshift家族算法实现
*/
class XorshiftFamily {
// 常用参数组合(经过验证的优质参数)
private const PARAMS = [
// 32位版本
'32' => [
[13, 17, 5], // 最常见
[13, 19, 3],
[15, 18, 2],
],
// 64位版本
'64' => [
[13, 7, 17],
[21, 35, 4],
[13, 7, 37],
],
// 128位版本
'128' => [
[11, 8, 19], [19, 3, 23]
]
];

/**
* 基础Xorshift32(单状态变量)
*/
class Xorshift32 {
private $state;

public function __construct($seed = null) {
$this->state = $seed ?? mt_rand(0, 0xffffffff);
// 确保状态不为0(0会导致始终为0)
if ($this->state == 0) {
$this->state = 1;
}
}

public function nextInt(): int {
$x = $this->state;
$x ^= $x << 13;
$x ^= $x >> 17;
$x ^= $x << 5;
$this->state = $x & 0xffffffff;
return $this->state;
}

public function nextFloat(): float {
return $this->nextInt() / 0xffffffff;
}

public function getState(): int {
return $this->state;
}

public function setState($state): void {
$this->state = $state & 0xffffffff;
if ($this->state == 0) {
$this->state = 1;
}
}
}

/**
* Xorshift64(64位版本)
*/
class Xorshift64 {
private $state;

public function __construct($seed = null) {
$seed = $seed ?? (mt_rand(0, 0xffffffff) << 32) | mt_rand(0, 0xffffffff);
$this->state = $seed & 0xffffffffffffffff;
if ($this->state == 0) {
$this->state = 1;
}
}

public function nextInt(): int {
$x = $this->state;
$x ^= $x << 13;
$x ^= $x >> 7;
$x ^= $x << 17;
$this->state = $x & 0xffffffffffffffff;
return $this->state >> 32; // 返回32位随机数
}

public function nextFloat(): float {
$intVal = $this->nextInt() & 0xffffffff;
return $intVal / 0xffffffff;
}

public function nextInt64(): int {
$x = $this->state;
$x ^= $x << 13;
$x ^= $x >> 7;
$x ^= $x << 17;
$this->state = $x & 0xffffffffffffffff;
return $this->state;
}
}

/**
* Xorshift128(4个32位状态,周期更长)
*/
class Xorshift128 {
private $state = [0, 0, 0, 0];

public function __construct($seed = null) {
if ($seed === null) {
$seed = mt_rand(0, 0xffffffff);
}

// 用种子初始化4个状态变量
$s = $seed & 0xffffffff;
$this->state[0] = $s;
$this->state[1] = ($s ^ 0x9e3779b9) & 0xffffffff; // 黄金分割率
$this->state[2] = ($s << 16) & 0xffffffff;
$this->state[3] = ($s >> 16) & 0xffffffff;

// 确保没有全0状态
if ($this->state[0] == 0 && $this->state[1] == 0 &&
$this->state[2] == 0 && $this->state[3] == 0) {
$this->state[0] = 1;
}

// 热身(丢弃前几个输出)
for ($i = 0; $i < 10; $i++) {
$this->nextInt();
}
}

public function nextInt(): int {
// Xorshift128+ 变体(更好的统计特性)
$s1 = $this->state[0];
$s0 = $this->state[1];

$this->state[0] = $s0;
$s1 ^= $s1 << 23;

$this->state[1] = $s1 ^ $s0 ^ ($s1 >> 17) ^ ($s0 >> 26);
$this->state[2] = $this->state[3];
$this->state[3] = $s0;

return ($this->state[1] + $s0) & 0xffffffff;
}

public function getState(): array {
return $this->state;
}
}

/**
* Xorshift*(改进版本,乘以常数)
*/
class XorshiftStar {
private $state;

public function __construct($seed = null) {
$this->state = $seed ?? mt_rand(0, 0xffffffff);
if ($this->state == 0) {
$this->state = 1;
}
}

public function nextInt(): int {
$x = $this->state;
$x ^= $x >> 12;
$x ^= $x << 25;
$x ^= $x >> 27;
$this->state = $x & 0xffffffff;

// 乘以常数改进分布
return ($this->state * 0x2545F4914F6CDD1D) & 0xffffffff;
}
}

/**
* Xoroshiro128+(更现代的变体)
*/
class Xoroshiro128Plus {
private $state = [0, 0];

public function __construct($seed = null) {
if ($seed === null) {
$seed = mt_rand(0, 0xffffffff);
}

$s = $seed & 0xffffffff;
$this->state[0] = $s;
$this->state[1] = ($s ^ 0x9e3779b9) & 0xffffffff;

// 热身
for ($i = 0; $i < 10; $i++) {
$this->nextInt();
}
}

public function nextInt(): int {
$s0 = $this->state[0];
$s1 = $this->state[1];
$result = ($s0 + $s1) & 0xffffffff;

$s1 ^= $s0;
$this->state[0] = (($s0 << 55) | ($s0 >> 9)) ^ $s1 ^ ($s1 << 14);
$this->state[1] = ($s1 << 36) | ($s1 >> 28);

return $result;
}

public function jump(): void {
// 实现跳跃函数,用于并行生成多个不重叠序列
$jump = [0xbeac0467eba5facb, 0xd86b048b86aa9922];

$s0 = 0;
$s1 = 0;

for ($i = 0; $i < count($jump); $i++) {
for ($b = 0; $b < 64; $b++) {
if ($jump[$i] & (1 << $b)) {
$s0 ^= $this->state[0];
$s1 ^= $this->state[1];
}
$this->nextInt();
}
}

$this->state[0] = $s0;
$this->state[1] = $s1;
}
}
}

?>

三、算法特性分析

1. 周期长度

算法变体 状态大小 周期长度 备注
Xorshift32 32位 2³²-1 约42.9亿
Xorshift64 64位 2⁶⁴-1 约1.84×10¹⁹
Xorshift128 128位 2¹²⁸-1 约3.4×10³⁸
Xoroshiro128+ 128位 2¹²⁸-1 现代变体

2. 速度对比

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
38
39
40
41
42
43
44
45
<?php

class XorshiftBenchmark {
public static function run() {
$iterations = 1000000;

$generators = [
'mt_rand' => function() { return mt_rand(); },
'xorshift32' => (new XorshiftFamily\Xorshift32())->nextInt(...),
'xorshift128' => (new XorshiftFamily\Xorshift128())->nextInt(...),
'xorshift*' => (new XorshiftFamily\XorshiftStar())->nextInt(...),
];

$results = [];

foreach ($generators as $name => $generator) {
$start = microtime(true);

for ($i = 0; $i < $iterations; $i++) {
$generator();
}

$end = microtime(true);
$time = $end - $start;
$results[$name] = [
'time' => $time,
'rate' => $iterations / $time
];
}

return $results;
}
}

// 运行基准测试
$benchmark = XorshiftBenchmark::run();
foreach ($benchmark as $name => $data) {
echo sprintf("%-15s: %6.2f ms, %8.0f ops/sec\n",
$name,
$data['time'] * 1000,
$data['rate']
);
}

?>

典型结果:

  • Xorshift32: 比 mt_rand 快 2-3 倍
  • Xorshift128: 比 mt_rand 快 1.5-2 倍
  • Xorshift*: 略慢于基础版本,但分布更好

四、数学原理详解

1. 线性变换的矩阵表示

Xorshift操作可以表示为GF(2)上的线性变换:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php

/**
* Xorshift的矩阵表示
*/
class XorshiftMatrix {
/**
* 将Xorshift操作表示为32×32的矩阵(GF(2))
*/
public static function getXorshiftMatrix($a = 13, $b = 17, $c = 5) {
$size = 32;
$matrix = array_fill(0, $size, array_fill(0, $size, 0));

// 单位矩阵
$identity = [];
for ($i = 0; $i < $size; $i++) {
$identity[$i] = array_fill(0, $size, 0);
$identity[$i][$i] = 1;
}

// 构建左移矩阵 L_a
$L = $identity;
for ($i = 0; $i < $size; $i++) {
if ($i + $a < $size) {
$L[$i][$i + $a] = 1;
}
}

// 构建右移矩阵 R_b
$R = $identity;
for ($i = 0; $i < $size; $i++) {
if ($i - $b >= 0) {
$R[$i][$i - $b] = 1;
}
}

// 计算复合矩阵: M = (I ⊕ L_c)(I ⊕ R_b)(I ⊕ L_a)
$temp = self::matrixAdd($identity, $L, $a); // I ⊕ L_a
$temp = self::matrixMultiply(self::matrixAdd($identity, $R, $b), $temp); // (I ⊕ R_b)(...)
$result = self::matrixMultiply(self::matrixAdd($identity, $L, $c), $temp); // (I ⊕ L_c)(...)

return $result;
}

/**
* 矩阵加法(GF(2)上的异或)
*/
private static function matrixAdd($A, $B, $shift = 0) {
$size = count($A);
$result = array_fill(0, $size, array_fill(0, $size, 0));

for ($i = 0; $i < $size; $i++) {
for ($j = 0; $j < $size; $j++) {
$result[$i][$j] = ($A[$i][$j] + $B[$i][$j]) % 2;
}
}

return $result;
}
}

?>

2. 可逆性证明

Xorshift操作是可逆的,这意味着存在逆操作:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php

/**
* Xorshift逆变换
*/
class XorshiftInverse {
/**
* 逆Xorshift32变换
* 给定output,求可能的输入state
*/
public static function reverseXorshift32($output, $a = 13, $b = 17, $c = 5) {
// 由于输出取了绝对值,可能有多个解
$possibleStates = [];

// 考虑正负两种情况
$positive = $output;
$negative = -$output & 0xffffffff;

foreach ([$positive, $negative] as $state) {
// 尝试逆变换
$reversed = self::inverseTransform($state, $a, $b, $c);
if ($reversed !== null) {
$possibleStates[] = $reversed;
}
}

return $possibleStates;
}

private static function inverseTransform($y, $a, $b, $c) {
// 逆第三阶段: y = x ^ (x << c)
$x = $y;
for ($i = 31; $i >= 0; $i--) {
if ($i >= $c) {
$bit = ($x >> ($i - $c)) & 1;
$x ^= $bit << $i;
}
}

// 逆第二阶段: x = w ^ (w >> b)
$w = $x;
for ($i = 0; $i < 32; $i++) {
if ($i + $b < 32) {
$bit = ($w >> ($i + $b)) & 1;
$w ^= $bit << $i;
}
}

// 逆第一阶段: w = z ^ (z << a)
$z = $w;
for ($i = 31; $i >= 0; $i--) {
if ($i >= $a) {
$bit = ($z >> ($i - $a)) & 1;
$z ^= $bit << $i;
}
}

return $z;
}
}

?>

五、改进与变体

1. Xorshift+(改善低维分布)

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
38
39
40
41
<?php

class XorshiftPlus {
private $state0;
private $state1;

public function __construct($seed = null) {
$seed = $seed ?? mt_rand();
$this->state0 = $seed;
$this->state1 = $seed ^ 0x9e3779b9;

// 热身
$this->nextInt();
$this->nextInt();
}

public function nextInt(): int {
$x = $this->state0;
$y = $this->state1;

$this->state0 = $y;
$x ^= $x << 23;
$this->state1 = $x ^ $y ^ ($x >> 17) ^ ($y >> 26);

return ($this->state1 + $y) & 0xffffffff;
}

/**
* 生成[0,1)的浮点数(53位精度)
*/
public function nextDouble(): float {
$high = $this->nextInt() & 0x1fffff; // 21位
$low = $this->nextInt() & 0xffffffff; // 32位

// 组合成53位整数,然后除以2^53
$value = ($high << 32) | $low;
return $value / 9007199254740992.0; // 2^53
}
}

?>

2. Xorshift128++(进一步改进)

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
<?php

class Xorshift128PlusPlus {
private $state = [0, 0, 0, 0];

public function __construct($seed = null) {
$seed = $seed ?? mt_rand();

// 更好的初始化
$this->state[0] = $seed;
$this->state[1] = $seed ^ 0x9e3779b9;
$this->state[2] = ($seed << 16) | ($seed >> 16);
$this->state[3] = ~$seed;

// 长热身
for ($i = 0; $i < 20; $i++) {
$this->nextInt();
}
}

public function nextInt(): int {
$s1 = $this->state[0];
$s0 = $this->state[1];
$this->state[0] = $s0;

$s1 ^= $s1 << 23;
$s1 ^= $s1 >> 18;
$this->state[1] = $s1 ^ $s0 ^ ($s1 >> 5) ^ ($s0 >> 6);

$this->state[2] = $this->state[3];
$this->state[3] = $s0;

return ($this->state[1] + $s0 + $this->state[2]) & 0xffffffff;
}
}

?>

六、应用场景

1. 游戏开发中的随机生成

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<?php

/**
* 游戏随机系统(使用Xorshift)
*/
class GameRandomSystem {
private $rng;
private $seed;

public function __construct($seed = null) {
$this->seed = $seed ?? time();
$this->rng = new XorshiftFamily\Xorshift128($this->seed);

// 记录种子用于调试
$this->logSeed();
}

/**
* 生成随机位置
*/
public function randomPosition($minX, $maxX, $minY, $maxY): array {
return [
'x' => $this->randomInt($minX, $maxX),
'y' => $this->randomInt($minY, $maxY)
];
}

/**
* 加权随机选择
*/
public function weightedChoice(array $items, array $weights) {
$totalWeight = array_sum($weights);
$random = $this->randomFloat(0, $totalWeight);

$cumulative = 0;
foreach ($items as $i => $item) {
$cumulative += $weights[$i];
if ($random <= $cumulative) {
return $item;
}
}

return end($items);
}

/**
* 洗牌(Fisher-Yates算法)
*/
public function shuffle(array $array): array {
$result = $array;
$count = count($result);

for ($i = $count - 1; $i > 0; $i--) {
$j = $this->randomInt(0, $i);
list($result[$i], $result[$j]) = [$result[$j], $result[$i]];
}

return $result;
}

/**
* 生成随机姓名
*/
public function randomName(): string {
$prefixes = ['A', 'Be', 'De', 'El', 'Fa', 'Jo', 'Ki', 'La', 'Ma', 'Na', 'O', 'Pa', 'Re', 'Si', 'Ta', 'Va'];
$suffixes = ['an', 'ar', 'el', 'en', 'ia', 'ic', 'ie', 'in', 'is', 'on', 'or', 'us', 'yn', 'yth'];

$prefix = $prefixes[$this->randomInt(0, count($prefixes) - 1)];
$suffix = $suffixes[$this->randomInt(0, count($suffixes) - 1)];

return $prefix . $suffix;
}

private function randomInt($min, $max): int {
$range = $max - $min + 1;
return $min + ($this->rng->nextInt() % $range);
}

private function randomFloat($min, $max): float {
$range = $max - $min;
return $min + ($this->rng->nextFloat() * $range);
}
}

?>

2. 蒙特卡洛模拟

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?php

class MonteCarloSimulation {
private $rng;

public function __construct() {
$this->rng = new XorshiftFamily\Xorshift128();
}

/**
* 估算圆周率π
*/
public function estimatePi($iterations = 1000000): float {
$inside = 0;

for ($i = 0; $i < $iterations; $i++) {
$x = $this->rng->nextFloat(); // [0, 1)
$y = $this->rng->nextFloat();

// 检查点是否在单位圆内
if ($x * $x + $y * $y <= 1.0) {
$inside++;
}
}

return 4.0 * $inside / $iterations;
}

/**
* 期权定价(Black-Scholes蒙特卡洛模拟)
*/
public function optionPrice(
float $S0, // 当前股价
float $K, // 行权价
float $r, // 无风险利率
float $sigma, // 波动率
float $T, // 到期时间(年)
int $iterations = 100000
): float {
$total = 0;

for ($i = 0; $i < $iterations; $i++) {
// 生成标准正态分布随机数(Box-Muller变换)
$u1 = $this->rng->nextFloat();
$u2 = $this->rng->nextFloat();

$z0 = sqrt(-2.0 * log($u1)) * cos(2.0 * M_PI * $u2);

// 计算到期股价
$ST = $S0 * exp(($r - 0.5 * $sigma * $sigma) * $T + $sigma * sqrt($T) * $z0);

// 计算期权收益
$payoff = max($ST - $K, 0);
$total += $payoff;
}

// 贴现求现值
$meanPayoff = $total / $iterations;
return exp(-$r * $T) * $meanPayoff;
}
}

?>

七、安全性分析

1. 不是密码学安全的

重要警告:Xorshift不适用于密码学!

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?php

/**
* 演示Xorshift的预测攻击
*/
class XorshiftPredictor {
/**
* 通过观察输出序列预测后续值
*/
public static function predict(array $observed, $a = 13, $b = 17, $c = 5) {
if (count($observed) < 2) {
throw new Exception("需要至少2个观察值");
}

// 尝试从观察值恢复状态
$possibleStates = [];

// 对每个可能的符号组合
$signCombinations = self::generateSignCombinations(count($observed));

foreach ($signCombinations as $signs) {
$candidateStates = [];

// 为每个观察值应用符号
for ($i = 0; $i < count($observed); $i++) {
if ($signs[$i] == '+') {
$candidateStates[] = $observed[$i];
} else {
$candidateStates[] = -$observed[$i] & 0xffffffff;
}
}

// 检查这些状态是否构成有效序列
if (self::isValidSequence($candidateStates, $a, $b, $c)) {
// 找到有效序列,预测下一个值
$lastState = end($candidateStates);
$nextState = self::xorshiftTransform($lastState, $a, $b, $c);
$possibleStates[] = abs($nextState);
}
}

return $possibleStates;
}

private static function xorshiftTransform($x, $a, $b, $c) {
$x ^= $x << $a;
$x ^= $x >> $b;
$x ^= $x << $c;
return $x & 0xffffffff;
}
}

?>

2. 加固方案

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
38
39
40
41
42
43
44
45
<?php

/**
* 加密安全的伪随机数生成器
*/
class SecureRNG {
private $xorshift;
private $counter;
private $key;

public function __construct($seed = null) {
$seed = $seed ?? random_bytes(16);

// 使用密码学安全种子初始化
$this->key = hash('sha256', $seed, true);
$this->counter = 0;

// 使用Xorshift作为快速源
$this->xorshift = new XorshiftFamily\Xorshift128(
unpack('V', substr($this->key, 0, 4))[1]
);
}

public function nextSecureInt(): int {
$this->counter++;

// 混合多个来源
$xorshiftVal = $this->xorshift->nextInt();
$hashInput = $this->key . pack('V', $this->counter);
$hashVal = unpack('V', hash('sha256', $hashInput, true))[1];

// 使用加密学安全的混合
return ($xorshiftVal ^ $hashVal) & 0xffffffff;
}

public function nextSecureBytes($length): string {
$result = '';
while (strlen($result) < $length) {
$result .= pack('V', $this->nextSecureInt());
}
return substr($result, 0, $length);
}
}

?>

八、最佳实践总结

1. 选择指南

使用场景 推荐算法 理由
游戏随机数 Xorshift128+ 速度快,分布好
模拟/科学计算 Xoroshiro128+ 统计特性优秀
需要可重复性 任意Xorshift + 记录种子 确定性输出
密码学/安全 不要用Xorshift 使用CSPRNG

2. 实现建议

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php

// 最佳实践示例
class BestPracticeRNG {
private $rng;
private $seed;

public function __construct($seed = null) {
// 1. 提供多种种子选项
if ($seed === null) {
$seed = mt_rand();
} elseif (is_string($seed)) {
$seed = crc32($seed);
}

$this->seed = $seed;

// 2. 选择适当的算法
$this->rng = new XorshiftFamily\Xorshift128($seed);

// 3. 热身(避免初始状态相关问题)
$this->warmUp();
}

private function warmUp() {
for ($i = 0; $i < 10; $i++) {
$this->rng->nextInt();
}
}

// 4. 提供多种分布
public function uniform($min = 0, $max = 1): float {
return $min + ($this->rng->nextFloat() * ($max - $min));
}

public function normal($mean = 0, $stddev = 1): float {
// Box-Muller变换
$u1 = $this->uniform();
$u2 = $this->uniform();

$z0 = sqrt(-2.0 * log($u1)) * cos(2.0 * M_PI * $u2);
return $mean + $z0 * $stddev;
}

// 5. 提供状态保存/恢复
public function saveState(): array {
return [
'seed' => $this->seed,
'rng_state' => $this->rng->getState(),
'save_time' => time()
];
}
}

?>

九、历史与发展

1. 发展历程

1
2
3
4
5
2003: George Marsaglia 发表Xorshift论文
2006: 发现参数 (13, 17, 5) 提供良好特性
2014: Sebastiano Vigna 提出Xoroshiro系列
2018: Xoshiro (旋转扩展) 进一步改进
2020: 广泛用于游戏引擎和模拟框架

2. 现代替代品

虽然Xorshift仍然优秀,但现代替代品包括:

  • PCG (Permuted Congruential Generator)
  • SplitMix64
  • Threefry (并行随机数生成)

结论

Xorshift算法在性能质量之间取得了极佳的平衡,使其成为非密码学应用的理想选择。其简单性、速度和良好特性使其在游戏开发、模拟和许多其他领域广受欢迎。

核心优势:

  • 极快的速度(几个位操作)
  • 可重复性(确定性输出)
  • 长周期(2ⁿ-1)
  • 易于实现和理解

主要限制:

  • 不适用于密码学
  • 某些变体存在统计缺陷
  • 可能需要热身以避免初始状态问题

对于大多数应用来说,选择合适的Xorshift变体(如Xorshift128+或Xoroshiro128+)并提供适当的初始化和测试,将提供出色的随机数生成性能。


文章作者: Crazy Boy
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Crazy Boy !
评 论
 上一篇
飞轮效应:从艰难启动到势不可挡的系统增长哲学
飞轮效应:从艰难启动到势不可挡的系统增长哲学
在商业战略与个人成长领域,“飞轮效应”已成为解释成功从何而来的核心模型。它描绘了一种自我强化的增长循环:一个系统通过一系列紧密耦合的环节,将上一环节的输出转化为下一环节的动力,初始启动虽然艰难,但一旦转动起来,动量会越来越大,最终形成势不可
2026-02-04
下一篇 
启发式算法:在计算的迷宫中寻找智慧的捷径
启发式算法:在计算的迷宫中寻找智慧的捷径
在计算机科学和运筹学领域,我们常常面对一些令人望而生畏的复杂问题:如何为上万个包裹规划最省油的配送路线?如何为上百万个晶体管设计最优的电路布局?如何为瞬息万变的股市找到最佳的交易策略? 这类问题在数学上通常被归类为 NP难(NP-hard)
2026-02-04

Xorshift算法是一种快速、轻量级的伪随机数生成器,由George Marsaglia于2003年提出。它以极少的计算量生成高质量的随机数序列,广泛应用于游戏开发、模拟和需要高性能随机数生成的场景。

一、算法核心原理

1. 基本思想

Xorshift基于线性反馈移位寄存器(LFSR)的变体,通过位移(shift)和异或(XOR)操作来改变内部状态。

2. 数学表示

对于32位版本,典型操作为:

1
2
3
x ^= x << a
x ^= x >> b
x ^= x << c

其中 a, b, c 是精心选择的常数。

二、完整算法实现

1. 不同位宽的Xorshift实现

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
<?php

/**
* Xorshift家族算法实现
*/
class XorshiftFamily {
// 常用参数组合(经过验证的优质参数)
private const PARAMS = [
// 32位版本
'32' => [
[13, 17, 5], // 最常见
[13, 19, 3],
[15, 18, 2],
],
// 64位版本
'64' => [
[13, 7, 17],
[21, 35, 4],
[13, 7, 37],
],
// 128位版本
'128' => [
[11, 8, 19], [19, 3, 23]
]
];

/**
* 基础Xorshift32(单状态变量)
*/
class Xorshift32 {
private $state;

public function __construct($seed = null) {
$this->state = $seed ?? mt_rand(0, 0xffffffff);
// 确保状态不为0(0会导致始终为0)
if ($this->state == 0) {
$this->state = 1;
}
}

public function nextInt(): int {
$x = $this->state;
$x ^= $x << 13;
$x ^= $x >> 17;
$x ^= $x << 5;
$this->state = $x & 0xffffffff;
return $this->state;
}

public function nextFloat(): float {
return $this->nextInt() / 0xffffffff;
}

public function getState(): int {
return $this->state;
}

public function setState($state): void {
$this->state = $state & 0xffffffff;
if ($this->state == 0) {
$this->state = 1;
}
}
}

/**
* Xorshift64(64位版本)
*/
class Xorshift64 {
private $state;

public function __construct($seed = null) {
$seed = $seed ?? (mt_rand(0, 0xffffffff) << 32) | mt_rand(0, 0xffffffff);
$this->state = $seed & 0xffffffffffffffff;
if ($this->state == 0) {
$this->state = 1;
}
}

public function nextInt(): int {
$x = $this->state;
$x ^= $x << 13;
$x ^= $x >> 7;
$x ^= $x << 17;
$this->state = $x & 0xffffffffffffffff;
return $this->state >> 32; // 返回32位随机数
}

public function nextFloat(): float {
$intVal = $this->nextInt() & 0xffffffff;
return $intVal / 0xffffffff;
}

public function nextInt64(): int {
$x = $this->state;
$x ^= $x << 13;
$x ^= $x >> 7;
$x ^= $x << 17;
$this->state = $x & 0xffffffffffffffff;
return $this->state;
}
}

/**
* Xorshift128(4个32位状态,周期更长)
*/
class Xorshift128 {
private $state = [0, 0, 0, 0];

public function __construct($seed = null) {
if ($seed === null) {
$seed = mt_rand(0, 0xffffffff);
}

// 用种子初始化4个状态变量
$s = $seed & 0xffffffff;
$this->state[0] = $s;
$this->state[1] = ($s ^ 0x9e3779b9) & 0xffffffff; // 黄金分割率
$this->state[2] = ($s << 16) & 0xffffffff;
$this->state[3] = ($s >> 16) & 0xffffffff;

// 确保没有全0状态
if ($this->state[0] == 0 && $this->state[1] == 0 &&
$this->state[2] == 0 && $this->state[3] == 0) {
$this->state[0] = 1;
}

// 热身(丢弃前几个输出)
for ($i = 0; $i < 10; $i++) {
$this->nextInt();
}
}

public function nextInt(): int {
// Xorshift128+ 变体(更好的统计特性)
$s1 = $this->state[0];
$s0 = $this->state[1];

$this->state[0] = $s0;
$s1 ^= $s1 << 23;

$this->state[1] = $s1 ^ $s0 ^ ($s1 >> 17) ^ ($s0 >> 26);
$this->state[2] = $this->state[3];
$this->state[3] = $s0;

return ($this->state[1] + $s0) & 0xffffffff;
}

public function getState(): array {
return $this->state;
}
}

/**
* Xorshift*(改进版本,乘以常数)
*/
class XorshiftStar {
private $state;

public function __construct($seed = null) {
$this->state = $seed ?? mt_rand(0, 0xffffffff);
if ($this->state == 0) {
$this->state = 1;
}
}

public function nextInt(): int {
$x = $this->state;
$x ^= $x >> 12;
$x ^= $x << 25;
$x ^= $x >> 27;
$this->state = $x & 0xffffffff;

// 乘以常数改进分布
return ($this->state * 0x2545F4914F6CDD1D) & 0xffffffff;
}
}

/**
* Xoroshiro128+(更现代的变体)
*/
class Xoroshiro128Plus {
private $state = [0, 0];

public function __construct($seed = null) {
if ($seed === null) {
$seed = mt_rand(0, 0xffffffff);
}

$s = $seed & 0xffffffff;
$this->state[0] = $s;
$this->state[1] = ($s ^ 0x9e3779b9) & 0xffffffff;

// 热身
for ($i = 0; $i < 10; $i++) {
$this->nextInt();
}
}

public function nextInt(): int {
$s0 = $this->state[0];
$s1 = $this->state[1];
$result = ($s0 + $s1) & 0xffffffff;

$s1 ^= $s0;
$this->state[0] = (($s0 << 55) | ($s0 >> 9)) ^ $s1 ^ ($s1 << 14);
$this->state[1] = ($s1 << 36) | ($s1 >> 28);

return $result;
}

public function jump(): void {
// 实现跳跃函数,用于并行生成多个不重叠序列
$jump = [0xbeac0467eba5facb, 0xd86b048b86aa9922];

$s0 = 0;
$s1 = 0;

for ($i = 0; $i < count($jump); $i++) {
for ($b = 0; $b < 64; $b++) {
if ($jump[$i] & (1 << $b)) {
$s0 ^= $this->state[0];
$s1 ^= $this->state[1];
}
$this->nextInt();
}
}

$this->state[0] = $s0;
$this->state[1] = $s1;
}
}
}

?>

三、算法特性分析

1. 周期长度

算法变体 状态大小 周期长度 备注
Xorshift32 32位 2³²-1 约42.9亿
Xorshift64 64位 2⁶⁴-1 约1.84×10¹⁹
Xorshift128 128位 2¹²⁸-1 约3.4×10³⁸
Xoroshiro128+ 128位 2¹²⁸-1 现代变体

2. 速度对比

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
38
39
40
41
42
43
44
45
<?php

class XorshiftBenchmark {
public static function run() {
$iterations = 1000000;

$generators = [
'mt_rand' => function() { return mt_rand(); },
'xorshift32' => (new XorshiftFamily\Xorshift32())->nextInt(...),
'xorshift128' => (new XorshiftFamily\Xorshift128())->nextInt(...),
'xorshift*' => (new XorshiftFamily\XorshiftStar())->nextInt(...),
];

$results = [];

foreach ($generators as $name => $generator) {
$start = microtime(true);

for ($i = 0; $i < $iterations; $i++) {
$generator();
}

$end = microtime(true);
$time = $end - $start;
$results[$name] = [
'time' => $time,
'rate' => $iterations / $time
];
}

return $results;
}
}

// 运行基准测试
$benchmark = XorshiftBenchmark::run();
foreach ($benchmark as $name => $data) {
echo sprintf("%-15s: %6.2f ms, %8.0f ops/sec\n",
$name,
$data['time'] * 1000,
$data['rate']
);
}

?>

典型结果:

  • Xorshift32: 比 mt_rand 快 2-3 倍
  • Xorshift128: 比 mt_rand 快 1.5-2 倍
  • Xorshift*: 略慢于基础版本,但分布更好

四、数学原理详解

1. 线性变换的矩阵表示

Xorshift操作可以表示为GF(2)上的线性变换:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php

/**
* Xorshift的矩阵表示
*/
class XorshiftMatrix {
/**
* 将Xorshift操作表示为32×32的矩阵(GF(2))
*/
public static function getXorshiftMatrix($a = 13, $b = 17, $c = 5) {
$size = 32;
$matrix = array_fill(0, $size, array_fill(0, $size, 0));

// 单位矩阵
$identity = [];
for ($i = 0; $i < $size; $i++) {
$identity[$i] = array_fill(0, $size, 0);
$identity[$i][$i] = 1;
}

// 构建左移矩阵 L_a
$L = $identity;
for ($i = 0; $i < $size; $i++) {
if ($i + $a < $size) {
$L[$i][$i + $a] = 1;
}
}

// 构建右移矩阵 R_b
$R = $identity;
for ($i = 0; $i < $size; $i++) {
if ($i - $b >= 0) {
$R[$i][$i - $b] = 1;
}
}

// 计算复合矩阵: M = (I ⊕ L_c)(I ⊕ R_b)(I ⊕ L_a)
$temp = self::matrixAdd($identity, $L, $a); // I ⊕ L_a
$temp = self::matrixMultiply(self::matrixAdd($identity, $R, $b), $temp); // (I ⊕ R_b)(...)
$result = self::matrixMultiply(self::matrixAdd($identity, $L, $c), $temp); // (I ⊕ L_c)(...)

return $result;
}

/**
* 矩阵加法(GF(2)上的异或)
*/
private static function matrixAdd($A, $B, $shift = 0) {
$size = count($A);
$result = array_fill(0, $size, array_fill(0, $size, 0));

for ($i = 0; $i < $size; $i++) {
for ($j = 0; $j < $size; $j++) {
$result[$i][$j] = ($A[$i][$j] + $B[$i][$j]) % 2;
}
}

return $result;
}
}

?>

2. 可逆性证明

Xorshift操作是可逆的,这意味着存在逆操作:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php

/**
* Xorshift逆变换
*/
class XorshiftInverse {
/**
* 逆Xorshift32变换
* 给定output,求可能的输入state
*/
public static function reverseXorshift32($output, $a = 13, $b = 17, $c = 5) {
// 由于输出取了绝对值,可能有多个解
$possibleStates = [];

// 考虑正负两种情况
$positive = $output;
$negative = -$output & 0xffffffff;

foreach ([$positive, $negative] as $state) {
// 尝试逆变换
$reversed = self::inverseTransform($state, $a, $b, $c);
if ($reversed !== null) {
$possibleStates[] = $reversed;
}
}

return $possibleStates;
}

private static function inverseTransform($y, $a, $b, $c) {
// 逆第三阶段: y = x ^ (x << c)
$x = $y;
for ($i = 31; $i >= 0; $i--) {
if ($i >= $c) {
$bit = ($x >> ($i - $c)) & 1;
$x ^= $bit << $i;
}
}

// 逆第二阶段: x = w ^ (w >> b)
$w = $x;
for ($i = 0; $i < 32; $i++) {
if ($i + $b < 32) {
$bit = ($w >> ($i + $b)) & 1;
$w ^= $bit << $i;
}
}

// 逆第一阶段: w = z ^ (z << a)
$z = $w;
for ($i = 31; $i >= 0; $i--) {
if ($i >= $a) {
$bit = ($z >> ($i - $a)) & 1;
$z ^= $bit << $i;
}
}

return $z;
}
}

?>

五、改进与变体

1. Xorshift+(改善低维分布)

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
38
39
40
41
<?php

class XorshiftPlus {
private $state0;
private $state1;

public function __construct($seed = null) {
$seed = $seed ?? mt_rand();
$this->state0 = $seed;
$this->state1 = $seed ^ 0x9e3779b9;

// 热身
$this->nextInt();
$this->nextInt();
}

public function nextInt(): int {
$x = $this->state0;
$y = $this->state1;

$this->state0 = $y;
$x ^= $x << 23;
$this->state1 = $x ^ $y ^ ($x >> 17) ^ ($y >> 26);

return ($this->state1 + $y) & 0xffffffff;
}

/**
* 生成[0,1)的浮点数(53位精度)
*/
public function nextDouble(): float {
$high = $this->nextInt() & 0x1fffff; // 21位
$low = $this->nextInt() & 0xffffffff; // 32位

// 组合成53位整数,然后除以2^53
$value = ($high << 32) | $low;
return $value / 9007199254740992.0; // 2^53
}
}

?>

2. Xorshift128++(进一步改进)

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
<?php

class Xorshift128PlusPlus {
private $state = [0, 0, 0, 0];

public function __construct($seed = null) {
$seed = $seed ?? mt_rand();

// 更好的初始化
$this->state[0] = $seed;
$this->state[1] = $seed ^ 0x9e3779b9;
$this->state[2] = ($seed << 16) | ($seed >> 16);
$this->state[3] = ~$seed;

// 长热身
for ($i = 0; $i < 20; $i++) {
$this->nextInt();
}
}

public function nextInt(): int {
$s1 = $this->state[0];
$s0 = $this->state[1];
$this->state[0] = $s0;

$s1 ^= $s1 << 23;
$s1 ^= $s1 >> 18;
$this->state[1] = $s1 ^ $s0 ^ ($s1 >> 5) ^ ($s0 >> 6);

$this->state[2] = $this->state[3];
$this->state[3] = $s0;

return ($this->state[1] + $s0 + $this->state[2]) & 0xffffffff;
}
}

?>

六、应用场景

1. 游戏开发中的随机生成

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<?php

/**
* 游戏随机系统(使用Xorshift)
*/
class GameRandomSystem {
private $rng;
private $seed;

public function __construct($seed = null) {
$this->seed = $seed ?? time();
$this->rng = new XorshiftFamily\Xorshift128($this->seed);

// 记录种子用于调试
$this->logSeed();
}

/**
* 生成随机位置
*/
public function randomPosition($minX, $maxX, $minY, $maxY): array {
return [
'x' => $this->randomInt($minX, $maxX),
'y' => $this->randomInt($minY, $maxY)
];
}

/**
* 加权随机选择
*/
public function weightedChoice(array $items, array $weights) {
$totalWeight = array_sum($weights);
$random = $this->randomFloat(0, $totalWeight);

$cumulative = 0;
foreach ($items as $i => $item) {
$cumulative += $weights[$i];
if ($random <= $cumulative) {
return $item;
}
}

return end($items);
}

/**
* 洗牌(Fisher-Yates算法)
*/
public function shuffle(array $array): array {
$result = $array;
$count = count($result);

for ($i = $count - 1; $i > 0; $i--) {
$j = $this->randomInt(0, $i);
list($result[$i], $result[$j]) = [$result[$j], $result[$i]];
}

return $result;
}

/**
* 生成随机姓名
*/
public function randomName(): string {
$prefixes = ['A', 'Be', 'De', 'El', 'Fa', 'Jo', 'Ki', 'La', 'Ma', 'Na', 'O', 'Pa', 'Re', 'Si', 'Ta', 'Va'];
$suffixes = ['an', 'ar', 'el', 'en', 'ia', 'ic', 'ie', 'in', 'is', 'on', 'or', 'us', 'yn', 'yth'];

$prefix = $prefixes[$this->randomInt(0, count($prefixes) - 1)];
$suffix = $suffixes[$this->randomInt(0, count($suffixes) - 1)];

return $prefix . $suffix;
}

private function randomInt($min, $max): int {
$range = $max - $min + 1;
return $min + ($this->rng->nextInt() % $range);
}

private function randomFloat($min, $max): float {
$range = $max - $min;
return $min + ($this->rng->nextFloat() * $range);
}
}

?>

2. 蒙特卡洛模拟

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?php

class MonteCarloSimulation {
private $rng;

public function __construct() {
$this->rng = new XorshiftFamily\Xorshift128();
}

/**
* 估算圆周率π
*/
public function estimatePi($iterations = 1000000): float {
$inside = 0;

for ($i = 0; $i < $iterations; $i++) {
$x = $this->rng->nextFloat(); // [0, 1)
$y = $this->rng->nextFloat();

// 检查点是否在单位圆内
if ($x * $x + $y * $y <= 1.0) {
$inside++;
}
}

return 4.0 * $inside / $iterations;
}

/**
* 期权定价(Black-Scholes蒙特卡洛模拟)
*/
public function optionPrice(
float $S0, // 当前股价
float $K, // 行权价
float $r, // 无风险利率
float $sigma, // 波动率
float $T, // 到期时间(年)
int $iterations = 100000
): float {
$total = 0;

for ($i = 0; $i < $iterations; $i++) {
// 生成标准正态分布随机数(Box-Muller变换)
$u1 = $this->rng->nextFloat();
$u2 = $this->rng->nextFloat();

$z0 = sqrt(-2.0 * log($u1)) * cos(2.0 * M_PI * $u2);

// 计算到期股价
$ST = $S0 * exp(($r - 0.5 * $sigma * $sigma) * $T + $sigma * sqrt($T) * $z0);

// 计算期权收益
$payoff = max($ST - $K, 0);
$total += $payoff;
}

// 贴现求现值
$meanPayoff = $total / $iterations;
return exp(-$r * $T) * $meanPayoff;
}
}

?>

七、安全性分析

1. 不是密码学安全的

重要警告:Xorshift不适用于密码学!

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?php

/**
* 演示Xorshift的预测攻击
*/
class XorshiftPredictor {
/**
* 通过观察输出序列预测后续值
*/
public static function predict(array $observed, $a = 13, $b = 17, $c = 5) {
if (count($observed) < 2) {
throw new Exception("需要至少2个观察值");
}

// 尝试从观察值恢复状态
$possibleStates = [];

// 对每个可能的符号组合
$signCombinations = self::generateSignCombinations(count($observed));

foreach ($signCombinations as $signs) {
$candidateStates = [];

// 为每个观察值应用符号
for ($i = 0; $i < count($observed); $i++) {
if ($signs[$i] == '+') {
$candidateStates[] = $observed[$i];
} else {
$candidateStates[] = -$observed[$i] & 0xffffffff;
}
}

// 检查这些状态是否构成有效序列
if (self::isValidSequence($candidateStates, $a, $b, $c)) {
// 找到有效序列,预测下一个值
$lastState = end($candidateStates);
$nextState = self::xorshiftTransform($lastState, $a, $b, $c);
$possibleStates[] = abs($nextState);
}
}

return $possibleStates;
}

private static function xorshiftTransform($x, $a, $b, $c) {
$x ^= $x << $a;
$x ^= $x >> $b;
$x ^= $x << $c;
return $x & 0xffffffff;
}
}

?>

2. 加固方案

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
38
39
40
41
42
43
44
45
<?php

/**
* 加密安全的伪随机数生成器
*/
class SecureRNG {
private $xorshift;
private $counter;
private $key;

public function __construct($seed = null) {
$seed = $seed ?? random_bytes(16);

// 使用密码学安全种子初始化
$this->key = hash('sha256', $seed, true);
$this->counter = 0;

// 使用Xorshift作为快速源
$this->xorshift = new XorshiftFamily\Xorshift128(
unpack('V', substr($this->key, 0, 4))[1]
);
}

public function nextSecureInt(): int {
$this->counter++;

// 混合多个来源
$xorshiftVal = $this->xorshift->nextInt();
$hashInput = $this->key . pack('V', $this->counter);
$hashVal = unpack('V', hash('sha256', $hashInput, true))[1];

// 使用加密学安全的混合
return ($xorshiftVal ^ $hashVal) & 0xffffffff;
}

public function nextSecureBytes($length): string {
$result = '';
while (strlen($result) < $length) {
$result .= pack('V', $this->nextSecureInt());
}
return substr($result, 0, $length);
}
}

?>

八、最佳实践总结

1. 选择指南

使用场景 推荐算法 理由
游戏随机数 Xorshift128+ 速度快,分布好
模拟/科学计算 Xoroshiro128+ 统计特性优秀
需要可重复性 任意Xorshift + 记录种子 确定性输出
密码学/安全 不要用Xorshift 使用CSPRNG

2. 实现建议

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php

// 最佳实践示例
class BestPracticeRNG {
private $rng;
private $seed;

public function __construct($seed = null) {
// 1. 提供多种种子选项
if ($seed === null) {
$seed = mt_rand();
} elseif (is_string($seed)) {
$seed = crc32($seed);
}

$this->seed = $seed;

// 2. 选择适当的算法
$this->rng = new XorshiftFamily\Xorshift128($seed);

// 3. 热身(避免初始状态相关问题)
$this->warmUp();
}

private function warmUp() {
for ($i = 0; $i < 10; $i++) {
$this->rng->nextInt();
}
}

// 4. 提供多种分布
public function uniform($min = 0, $max = 1): float {
return $min + ($this->rng->nextFloat() * ($max - $min));
}

public function normal($mean = 0, $stddev = 1): float {
// Box-Muller变换
$u1 = $this->uniform();
$u2 = $this->uniform();

$z0 = sqrt(-2.0 * log($u1)) * cos(2.0 * M_PI * $u2);
return $mean + $z0 * $stddev;
}

// 5. 提供状态保存/恢复
public function saveState(): array {
return [
'seed' => $this->seed,
'rng_state' => $this->rng->getState(),
'save_time' => time()
];
}
}

?>

九、历史与发展

1. 发展历程

1
2
3
4
5
2003: George Marsaglia 发表Xorshift论文
2006: 发现参数 (13, 17, 5) 提供良好特性
2014: Sebastiano Vigna 提出Xoroshiro系列
2018: Xoshiro (旋转扩展) 进一步改进
2020: 广泛用于游戏引擎和模拟框架

2. 现代替代品

虽然Xorshift仍然优秀,但现代替代品包括:

  • PCG (Permuted Congruential Generator)
  • SplitMix64
  • Threefry (并行随机数生成)

结论

Xorshift算法在性能质量之间取得了极佳的平衡,使其成为非密码学应用的理想选择。其简单性、速度和良好特性使其在游戏开发、模拟和许多其他领域广受欢迎。

核心优势:

  • 极快的速度(几个位操作)
  • 可重复性(确定性输出)
  • 长周期(2ⁿ-1)
  • 易于实现和理解

主要限制:

  • 不适用于密码学
  • 某些变体存在统计缺陷
  • 可能需要热身以避免初始状态问题

对于大多数应用来说,选择合适的Xorshift变体(如Xorshift128+或Xoroshiro128+)并提供适当的初始化和测试,将提供出色的随机数生成性能。


文章作者: Crazy Boy
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Crazy Boy !
评 论
 上一篇
飞轮效应:从艰难启动到势不可挡的系统增长哲学
飞轮效应:从艰难启动到势不可挡的系统增长哲学
在商业战略与个人成长领域,“飞轮效应”已成为解释成功从何而来的核心模型。它描绘了一种自我强化的增长循环:一个系统通过一系列紧密耦合的环节,将上一环节的输出转化为下一环节的动力,初始启动虽然艰难,但一旦转动起来,动量会越来越大,最终形成势不可
2026-02-04
下一篇 
启发式算法:在计算的迷宫中寻找智慧的捷径
启发式算法:在计算的迷宫中寻找智慧的捷径
在计算机科学和运筹学领域,我们常常面对一些令人望而生畏的复杂问题:如何为上万个包裹规划最省油的配送路线?如何为上百万个晶体管设计最优的电路布局?如何为瞬息万变的股市找到最佳的交易策略? 这类问题在数学上通常被归类为 NP难(NP-hard)
2026-02-04

Xorshift算法是一种快速、轻量级的伪随机数生成器,由George Marsaglia于2003年提出。它以极少的计算量生成高质量的随机数序列,广泛应用于游戏开发、模拟和需要高性能随机数生成的场景。

一、算法核心原理

1. 基本思想

Xorshift基于线性反馈移位寄存器(LFSR)的变体,通过位移(shift)和异或(XOR)操作来改变内部状态。

2. 数学表示

对于32位版本,典型操作为:

1
2
3
x ^= x << a
x ^= x >> b
x ^= x << c

其中 a, b, c 是精心选择的常数。

二、完整算法实现

1. 不同位宽的Xorshift实现

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
<?php

/**
* Xorshift家族算法实现
*/
class XorshiftFamily {
// 常用参数组合(经过验证的优质参数)
private const PARAMS = [
// 32位版本
'32' => [
[13, 17, 5], // 最常见
[13, 19, 3],
[15, 18, 2],
],
// 64位版本
'64' => [
[13, 7, 17],
[21, 35, 4],
[13, 7, 37],
],
// 128位版本
'128' => [
[11, 8, 19], [19, 3, 23]
]
];

/**
* 基础Xorshift32(单状态变量)
*/
class Xorshift32 {
private $state;

public function __construct($seed = null) {
$this->state = $seed ?? mt_rand(0, 0xffffffff);
// 确保状态不为0(0会导致始终为0)
if ($this->state == 0) {
$this->state = 1;
}
}

public function nextInt(): int {
$x = $this->state;
$x ^= $x << 13;
$x ^= $x >> 17;
$x ^= $x << 5;
$this->state = $x & 0xffffffff;
return $this->state;
}

public function nextFloat(): float {
return $this->nextInt() / 0xffffffff;
}

public function getState(): int {
return $this->state;
}

public function setState($state): void {
$this->state = $state & 0xffffffff;
if ($this->state == 0) {
$this->state = 1;
}
}
}

/**
* Xorshift64(64位版本)
*/
class Xorshift64 {
private $state;

public function __construct($seed = null) {
$seed = $seed ?? (mt_rand(0, 0xffffffff) << 32) | mt_rand(0, 0xffffffff);
$this->state = $seed & 0xffffffffffffffff;
if ($this->state == 0) {
$this->state = 1;
}
}

public function nextInt(): int {
$x = $this->state;
$x ^= $x << 13;
$x ^= $x >> 7;
$x ^= $x << 17;
$this->state = $x & 0xffffffffffffffff;
return $this->state >> 32; // 返回32位随机数
}

public function nextFloat(): float {
$intVal = $this->nextInt() & 0xffffffff;
return $intVal / 0xffffffff;
}

public function nextInt64(): int {
$x = $this->state;
$x ^= $x << 13;
$x ^= $x >> 7;
$x ^= $x << 17;
$this->state = $x & 0xffffffffffffffff;
return $this->state;
}
}

/**
* Xorshift128(4个32位状态,周期更长)
*/
class Xorshift128 {
private $state = [0, 0, 0, 0];

public function __construct($seed = null) {
if ($seed === null) {
$seed = mt_rand(0, 0xffffffff);
}

// 用种子初始化4个状态变量
$s = $seed & 0xffffffff;
$this->state[0] = $s;
$this->state[1] = ($s ^ 0x9e3779b9) & 0xffffffff; // 黄金分割率
$this->state[2] = ($s << 16) & 0xffffffff;
$this->state[3] = ($s >> 16) & 0xffffffff;

// 确保没有全0状态
if ($this->state[0] == 0 && $this->state[1] == 0 &&
$this->state[2] == 0 && $this->state[3] == 0) {
$this->state[0] = 1;
}

// 热身(丢弃前几个输出)
for ($i = 0; $i < 10; $i++) {
$this->nextInt();
}
}

public function nextInt(): int {
// Xorshift128+ 变体(更好的统计特性)
$s1 = $this->state[0];
$s0 = $this->state[1];

$this->state[0] = $s0;
$s1 ^= $s1 << 23;

$this->state[1] = $s1 ^ $s0 ^ ($s1 >> 17) ^ ($s0 >> 26);
$this->state[2] = $this->state[3];
$this->state[3] = $s0;

return ($this->state[1] + $s0) & 0xffffffff;
}

public function getState(): array {
return $this->state;
}
}

/**
* Xorshift*(改进版本,乘以常数)
*/
class XorshiftStar {
private $state;

public function __construct($seed = null) {
$this->state = $seed ?? mt_rand(0, 0xffffffff);
if ($this->state == 0) {
$this->state = 1;
}
}

public function nextInt(): int {
$x = $this->state;
$x ^= $x >> 12;
$x ^= $x << 25;
$x ^= $x >> 27;
$this->state = $x & 0xffffffff;

// 乘以常数改进分布
return ($this->state * 0x2545F4914F6CDD1D) & 0xffffffff;
}
}

/**
* Xoroshiro128+(更现代的变体)
*/
class Xoroshiro128Plus {
private $state = [0, 0];

public function __construct($seed = null) {
if ($seed === null) {
$seed = mt_rand(0, 0xffffffff);
}

$s = $seed & 0xffffffff;
$this->state[0] = $s;
$this->state[1] = ($s ^ 0x9e3779b9) & 0xffffffff;

// 热身
for ($i = 0; $i < 10; $i++) {
$this->nextInt();
}
}

public function nextInt(): int {
$s0 = $this->state[0];
$s1 = $this->state[1];
$result = ($s0 + $s1) & 0xffffffff;

$s1 ^= $s0;
$this->state[0] = (($s0 << 55) | ($s0 >> 9)) ^ $s1 ^ ($s1 << 14);
$this->state[1] = ($s1 << 36) | ($s1 >> 28);

return $result;
}

public function jump(): void {
// 实现跳跃函数,用于并行生成多个不重叠序列
$jump = [0xbeac0467eba5facb, 0xd86b048b86aa9922];

$s0 = 0;
$s1 = 0;

for ($i = 0; $i < count($jump); $i++) {
for ($b = 0; $b < 64; $b++) {
if ($jump[$i] & (1 << $b)) {
$s0 ^= $this->state[0];
$s1 ^= $this->state[1];
}
$this->nextInt();
}
}

$this->state[0] = $s0;
$this->state[1] = $s1;
}
}
}

?>

三、算法特性分析

1. 周期长度

算法变体 状态大小 周期长度 备注
Xorshift32 32位 2³²-1 约42.9亿
Xorshift64 64位 2⁶⁴-1 约1.84×10¹⁹
Xorshift128 128位 2¹²⁸-1 约3.4×10³⁸
Xoroshiro128+ 128位 2¹²⁸-1 现代变体

2. 速度对比

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
38
39
40
41
42
43
44
45
<?php

class XorshiftBenchmark {
public static function run() {
$iterations = 1000000;

$generators = [
'mt_rand' => function() { return mt_rand(); },
'xorshift32' => (new XorshiftFamily\Xorshift32())->nextInt(...),
'xorshift128' => (new XorshiftFamily\Xorshift128())->nextInt(...),
'xorshift*' => (new XorshiftFamily\XorshiftStar())->nextInt(...),
];

$results = [];

foreach ($generators as $name => $generator) {
$start = microtime(true);

for ($i = 0; $i < $iterations; $i++) {
$generator();
}

$end = microtime(true);
$time = $end - $start;
$results[$name] = [
'time' => $time,
'rate' => $iterations / $time
];
}

return $results;
}
}

// 运行基准测试
$benchmark = XorshiftBenchmark::run();
foreach ($benchmark as $name => $data) {
echo sprintf("%-15s: %6.2f ms, %8.0f ops/sec\n",
$name,
$data['time'] * 1000,
$data['rate']
);
}

?>

典型结果:

  • Xorshift32: 比 mt_rand 快 2-3 倍
  • Xorshift128: 比 mt_rand 快 1.5-2 倍
  • Xorshift*: 略慢于基础版本,但分布更好

四、数学原理详解

1. 线性变换的矩阵表示

Xorshift操作可以表示为GF(2)上的线性变换:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php

/**
* Xorshift的矩阵表示
*/
class XorshiftMatrix {
/**
* 将Xorshift操作表示为32×32的矩阵(GF(2))
*/
public static function getXorshiftMatrix($a = 13, $b = 17, $c = 5) {
$size = 32;
$matrix = array_fill(0, $size, array_fill(0, $size, 0));

// 单位矩阵
$identity = [];
for ($i = 0; $i < $size; $i++) {
$identity[$i] = array_fill(0, $size, 0);
$identity[$i][$i] = 1;
}

// 构建左移矩阵 L_a
$L = $identity;
for ($i = 0; $i < $size; $i++) {
if ($i + $a < $size) {
$L[$i][$i + $a] = 1;
}
}

// 构建右移矩阵 R_b
$R = $identity;
for ($i = 0; $i < $size; $i++) {
if ($i - $b >= 0) {
$R[$i][$i - $b] = 1;
}
}

// 计算复合矩阵: M = (I ⊕ L_c)(I ⊕ R_b)(I ⊕ L_a)
$temp = self::matrixAdd($identity, $L, $a); // I ⊕ L_a
$temp = self::matrixMultiply(self::matrixAdd($identity, $R, $b), $temp); // (I ⊕ R_b)(...)
$result = self::matrixMultiply(self::matrixAdd($identity, $L, $c), $temp); // (I ⊕ L_c)(...)

return $result;
}

/**
* 矩阵加法(GF(2)上的异或)
*/
private static function matrixAdd($A, $B, $shift = 0) {
$size = count($A);
$result = array_fill(0, $size, array_fill(0, $size, 0));

for ($i = 0; $i < $size; $i++) {
for ($j = 0; $j < $size; $j++) {
$result[$i][$j] = ($A[$i][$j] + $B[$i][$j]) % 2;
}
}

return $result;
}
}

?>

2. 可逆性证明

Xorshift操作是可逆的,这意味着存在逆操作:

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?php

/**
* Xorshift逆变换
*/
class XorshiftInverse {
/**
* 逆Xorshift32变换
* 给定output,求可能的输入state
*/
public static function reverseXorshift32($output, $a = 13, $b = 17, $c = 5) {
// 由于输出取了绝对值,可能有多个解
$possibleStates = [];

// 考虑正负两种情况
$positive = $output;
$negative = -$output & 0xffffffff;

foreach ([$positive, $negative] as $state) {
// 尝试逆变换
$reversed = self::inverseTransform($state, $a, $b, $c);
if ($reversed !== null) {
$possibleStates[] = $reversed;
}
}

return $possibleStates;
}

private static function inverseTransform($y, $a, $b, $c) {
// 逆第三阶段: y = x ^ (x << c)
$x = $y;
for ($i = 31; $i >= 0; $i--) {
if ($i >= $c) {
$bit = ($x >> ($i - $c)) & 1;
$x ^= $bit << $i;
}
}

// 逆第二阶段: x = w ^ (w >> b)
$w = $x;
for ($i = 0; $i < 32; $i++) {
if ($i + $b < 32) {
$bit = ($w >> ($i + $b)) & 1;
$w ^= $bit << $i;
}
}

// 逆第一阶段: w = z ^ (z << a)
$z = $w;
for ($i = 31; $i >= 0; $i--) {
if ($i >= $a) {
$bit = ($z >> ($i - $a)) & 1;
$z ^= $bit << $i;
}
}

return $z;
}
}

?>

五、改进与变体

1. Xorshift+(改善低维分布)

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
38
39
40
41
<?php

class XorshiftPlus {
private $state0;
private $state1;

public function __construct($seed = null) {
$seed = $seed ?? mt_rand();
$this->state0 = $seed;
$this->state1 = $seed ^ 0x9e3779b9;

// 热身
$this->nextInt();
$this->nextInt();
}

public function nextInt(): int {
$x = $this->state0;
$y = $this->state1;

$this->state0 = $y;
$x ^= $x << 23;
$this->state1 = $x ^ $y ^ ($x >> 17) ^ ($y >> 26);

return ($this->state1 + $y) & 0xffffffff;
}

/**
* 生成[0,1)的浮点数(53位精度)
*/
public function nextDouble(): float {
$high = $this->nextInt() & 0x1fffff; // 21位
$low = $this->nextInt() & 0xffffffff; // 32位

// 组合成53位整数,然后除以2^53
$value = ($high << 32) | $low;
return $value / 9007199254740992.0; // 2^53
}
}

?>

2. Xorshift128++(进一步改进)

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
<?php

class Xorshift128PlusPlus {
private $state = [0, 0, 0, 0];

public function __construct($seed = null) {
$seed = $seed ?? mt_rand();

// 更好的初始化
$this->state[0] = $seed;
$this->state[1] = $seed ^ 0x9e3779b9;
$this->state[2] = ($seed << 16) | ($seed >> 16);
$this->state[3] = ~$seed;

// 长热身
for ($i = 0; $i < 20; $i++) {
$this->nextInt();
}
}

public function nextInt(): int {
$s1 = $this->state[0];
$s0 = $this->state[1];
$this->state[0] = $s0;

$s1 ^= $s1 << 23;
$s1 ^= $s1 >> 18;
$this->state[1] = $s1 ^ $s0 ^ ($s1 >> 5) ^ ($s0 >> 6);

$this->state[2] = $this->state[3];
$this->state[3] = $s0;

return ($this->state[1] + $s0 + $this->state[2]) & 0xffffffff;
}
}

?>

六、应用场景

1. 游戏开发中的随机生成

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<?php

/**
* 游戏随机系统(使用Xorshift)
*/
class GameRandomSystem {
private $rng;
private $seed;

public function __construct($seed = null) {
$this->seed = $seed ?? time();
$this->rng = new XorshiftFamily\Xorshift128($this->seed);

// 记录种子用于调试
$this->logSeed();
}

/**
* 生成随机位置
*/
public function randomPosition($minX, $maxX, $minY, $maxY): array {
return [
'x' => $this->randomInt($minX, $maxX),
'y' => $this->randomInt($minY, $maxY)
];
}

/**
* 加权随机选择
*/
public function weightedChoice(array $items, array $weights) {
$totalWeight = array_sum($weights);
$random = $this->randomFloat(0, $totalWeight);

$cumulative = 0;
foreach ($items as $i => $item) {
$cumulative += $weights[$i];
if ($random <= $cumulative) {
return $item;
}
}

return end($items);
}

/**
* 洗牌(Fisher-Yates算法)
*/
public function shuffle(array $array): array {
$result = $array;
$count = count($result);

for ($i = $count - 1; $i > 0; $i--) {
$j = $this->randomInt(0, $i);
list($result[$i], $result[$j]) = [$result[$j], $result[$i]];
}

return $result;
}

/**
* 生成随机姓名
*/
public function randomName(): string {
$prefixes = ['A', 'Be', 'De', 'El', 'Fa', 'Jo', 'Ki', 'La', 'Ma', 'Na', 'O', 'Pa', 'Re', 'Si', 'Ta', 'Va'];
$suffixes = ['an', 'ar', 'el', 'en', 'ia', 'ic', 'ie', 'in', 'is', 'on', 'or', 'us', 'yn', 'yth'];

$prefix = $prefixes[$this->randomInt(0, count($prefixes) - 1)];
$suffix = $suffixes[$this->randomInt(0, count($suffixes) - 1)];

return $prefix . $suffix;
}

private function randomInt($min, $max): int {
$range = $max - $min + 1;
return $min + ($this->rng->nextInt() % $range);
}

private function randomFloat($min, $max): float {
$range = $max - $min;
return $min + ($this->rng->nextFloat() * $range);
}
}

?>

2. 蒙特卡洛模拟

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?php

class MonteCarloSimulation {
private $rng;

public function __construct() {
$this->rng = new XorshiftFamily\Xorshift128();
}

/**
* 估算圆周率π
*/
public function estimatePi($iterations = 1000000): float {
$inside = 0;

for ($i = 0; $i < $iterations; $i++) {
$x = $this->rng->nextFloat(); // [0, 1)
$y = $this->rng->nextFloat();

// 检查点是否在单位圆内
if ($x * $x + $y * $y <= 1.0) {
$inside++;
}
}

return 4.0 * $inside / $iterations;
}

/**
* 期权定价(Black-Scholes蒙特卡洛模拟)
*/
public function optionPrice(
float $S0, // 当前股价
float $K, // 行权价
float $r, // 无风险利率
float $sigma, // 波动率
float $T, // 到期时间(年)
int $iterations = 100000
): float {
$total = 0;

for ($i = 0; $i < $iterations; $i++) {
// 生成标准正态分布随机数(Box-Muller变换)
$u1 = $this->rng->nextFloat();
$u2 = $this->rng->nextFloat();

$z0 = sqrt(-2.0 * log($u1)) * cos(2.0 * M_PI * $u2);

// 计算到期股价
$ST = $S0 * exp(($r - 0.5 * $sigma * $sigma) * $T + $sigma * sqrt($T) * $z0);

// 计算期权收益
$payoff = max($ST - $K, 0);
$total += $payoff;
}

// 贴现求现值
$meanPayoff = $total / $iterations;
return exp(-$r * $T) * $meanPayoff;
}
}

?>

七、安全性分析

1. 不是密码学安全的

重要警告:Xorshift不适用于密码学!

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?php

/**
* 演示Xorshift的预测攻击
*/
class XorshiftPredictor {
/**
* 通过观察输出序列预测后续值
*/
public static function predict(array $observed, $a = 13, $b = 17, $c = 5) {
if (count($observed) < 2) {
throw new Exception("需要至少2个观察值");
}

// 尝试从观察值恢复状态
$possibleStates = [];

// 对每个可能的符号组合
$signCombinations = self::generateSignCombinations(count($observed));

foreach ($signCombinations as $signs) {
$candidateStates = [];

// 为每个观察值应用符号
for ($i = 0; $i < count($observed); $i++) {
if ($signs[$i] == '+') {
$candidateStates[] = $observed[$i];
} else {
$candidateStates[] = -$observed[$i] & 0xffffffff;
}
}

// 检查这些状态是否构成有效序列
if (self::isValidSequence($candidateStates, $a, $b, $c)) {
// 找到有效序列,预测下一个值
$lastState = end($candidateStates);
$nextState = self::xorshiftTransform($lastState, $a, $b, $c);
$possibleStates[] = abs($nextState);
}
}

return $possibleStates;
}

private static function xorshiftTransform($x, $a, $b, $c) {
$x ^= $x << $a;
$x ^= $x >> $b;
$x ^= $x << $c;
return $x & 0xffffffff;
}
}

?>

2. 加固方案

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
38
39
40
41
42
43
44
45
<?php

/**
* 加密安全的伪随机数生成器
*/
class SecureRNG {
private $xorshift;
private $counter;
private $key;

public function __construct($seed = null) {
$seed = $seed ?? random_bytes(16);

// 使用密码学安全种子初始化
$this->key = hash('sha256', $seed, true);
$this->counter = 0;

// 使用Xorshift作为快速源
$this->xorshift = new XorshiftFamily\Xorshift128(
unpack('V', substr($this->key, 0, 4))[1]
);
}

public function nextSecureInt(): int {
$this->counter++;

// 混合多个来源
$xorshiftVal = $this->xorshift->nextInt();
$hashInput = $this->key . pack('V', $this->counter);
$hashVal = unpack('V', hash('sha256', $hashInput, true))[1];

// 使用加密学安全的混合
return ($xorshiftVal ^ $hashVal) & 0xffffffff;
}

public function nextSecureBytes($length): string {
$result = '';
while (strlen($result) < $length) {
$result .= pack('V', $this->nextSecureInt());
}
return substr($result, 0, $length);
}
}

?>

八、最佳实践总结

1. 选择指南

使用场景 推荐算法 理由
游戏随机数 Xorshift128+ 速度快,分布好
模拟/科学计算 Xoroshiro128+ 统计特性优秀
需要可重复性 任意Xorshift + 记录种子 确定性输出
密码学/安全 不要用Xorshift 使用CSPRNG

2. 实现建议

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<?php

// 最佳实践示例
class BestPracticeRNG {
private $rng;
private $seed;

public function __construct($seed = null) {
// 1. 提供多种种子选项
if ($seed === null) {
$seed = mt_rand();
} elseif (is_string($seed)) {
$seed = crc32($seed);
}

$this->seed = $seed;

// 2. 选择适当的算法
$this->rng = new XorshiftFamily\Xorshift128($seed);

// 3. 热身(避免初始状态相关问题)
$this->warmUp();
}

private function warmUp() {
for ($i = 0; $i < 10; $i++) {
$this->rng->nextInt();
}
}

// 4. 提供多种分布
public function uniform($min = 0, $max = 1): float {
return $min + ($this->rng->nextFloat() * ($max - $min));
}

public function normal($mean = 0, $stddev = 1): float {
// Box-Muller变换
$u1 = $this->uniform();
$u2 = $this->uniform();

$z0 = sqrt(-2.0 * log($u1)) * cos(2.0 * M_PI * $u2);
return $mean + $z0 * $stddev;
}

// 5. 提供状态保存/恢复
public function saveState(): array {
return [
'seed' => $this->seed,
'rng_state' => $this->rng->getState(),
'save_time' => time()
];
}
}

?>

九、历史与发展

1. 发展历程

1
2
3
4
5
2003: George Marsaglia 发表Xorshift论文
2006: 发现参数 (13, 17, 5) 提供良好特性
2014: Sebastiano Vigna 提出Xoroshiro系列
2018: Xoshiro (旋转扩展) 进一步改进
2020: 广泛用于游戏引擎和模拟框架

2. 现代替代品

虽然Xorshift仍然优秀,但现代替代品包括:

  • PCG (Permuted Congruential Generator)
  • SplitMix64
  • Threefry (并行随机数生成)

结论

Xorshift算法在性能质量之间取得了极佳的平衡,使其成为非密码学应用的理想选择。其简单性、速度和良好特性使其在游戏开发、模拟和许多其他领域广受欢迎。

核心优势:

  • 极快的速度(几个位操作)
  • 可重复性(确定性输出)
  • 长周期(2ⁿ-1)
  • 易于实现和理解

主要限制:

  • 不适用于密码学
  • 某些变体存在统计缺陷
  • 可能需要热身以避免初始状态问题

对于大多数应用来说,选择合适的Xorshift变体(如Xorshift128+或Xoroshiro128+)并提供适当的初始化和测试,将提供出色的随机数生成性能。


文章作者: Crazy Boy
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Crazy Boy !
评 论
 上一篇
飞轮效应:从艰难启动到势不可挡的系统增长哲学
飞轮效应:从艰难启动到势不可挡的系统增长哲学
在商业战略与个人成长领域,“飞轮效应”已成为解释成功从何而来的核心模型。它描绘了一种自我强化的增长循环:一个系统通过一系列紧密耦合的环节,将上一环节的输出转化为下一环节的动力,初始启动虽然艰难,但一旦转动起来,动量会越来越大,最终形成势不可
2026-02-04
下一篇 
启发式算法:在计算的迷宫中寻找智慧的捷径
启发式算法:在计算的迷宫中寻找智慧的捷径
在计算机科学和运筹学领域,我们常常面对一些令人望而生畏的复杂问题:如何为上万个包裹规划最省油的配送路线?如何为上百万个晶体管设计最优的电路布局?如何为瞬息万变的股市找到最佳的交易策略? 这类问题在数学上通常被归类为 NP难(NP-hard)
2026-02-04
  目录
  目录
  目录
hexo