随机数的基本要求是:
1. 能覆盖每个值。假如要在[1,10]之间取随机数,如果能取到1,2,3,4,5,6,7,9,10却取不到8,那这不是一个满足要求的随机数算法。
2. 各个值的概率相等。假使在[1,10]之间取随机数,每个数字被取到的概率都是
1
10
\frac1{10}
101。
3. 满足“随机性”,就是说不要能看得出规律。如果顺序产生数字肯定能满足上述两点要求,但是就不随机了。
随机数的基本算法,是这样的:
假设随机数函数为f(x),种子为seed。
那么第一个随机数
x
0
x_0
x0是f(seed).
第二个随机数
x
1
x_1
x1是
f
(
x
0
)
f(x_0)
f(x0),这样一直下去,产生一个随机数序列。
第N个随机数就是fn(seed).
所以这是个递归算法。随机数是一个系列,要得到第N个随机数,只能计算N次。
Marsaglia发明了xorshift算法,用于计算随机数,是运算速度比较快的随机数算法。在Java的ConcurrentSkipListMap和ConcurrentSkipListSet都用到了这种随机数算法。
xorshift伪随机数其基本算法是三个常量x,y,z。一般取值是13,17 和5。代码如下:
package com.youngthing.xorshift;
/**
* xorshift
* created at 04/04/2022
*
* @author 花书粉丝
* <a href="mailto://yujianbo@chtwm.com">yujianbo@chtwm.com</a>
* @since 1.0.0
*/
public class RandomGenerator {
private int r;
public RandomGenerator(int seed) {
this.r = seed;
}
public int next() {
r ^= r << 13;
r ^= r >>> 17;
r ^= r << 5;
return r;
}
}
至于如何证明这种算法能满足以上三条要求,网上有证明过程,而且给出了其他组合,比如26,15,17。并不是任意三个数字的组合都可以满足随机数的两条要求的。比如1,2,3这个组合肯定就不行。