# 解密随机数生成器（二）——从java源码看线性同余算法

Random

Java中的Random类生成的是伪随机数，使用的是48-bit的种子，然后调用一个linear congruential formula线性同余方程（Donald Knuth的编程艺术的3.2.1节）

Random实例不是安全可靠的加密，可以使用java.security.SecureRandom来提供一个可靠的加密。

Random implements Serializable 可序列化

AtomicLong seed 原子变量

1、同余法

```    private static final AtomicLong seedUniquifier
= new AtomicLong(8682522807148012L);```
```/**
* Creates a new random number generator. This constructor sets
* the seed of the random number generator to a value very likely
* to be distinct from any other invocation of this constructor.
*/
public Random() {
this(seedUniquifier() ^ System.nanoTime());
}

private static long seedUniquifier() {
// L‘Ecuyer, "Tables of Linear Congruential Generators of
// Different Sizes and Good Lattice Structure", 1999
for (;;) {
long current = seedUniquifier.get();
long next = current * 181783497276652981L;
if (seedUniquifier.compareAndSet(current, next))
return next;
}
}

private static final AtomicLong seedUniquifier
= new AtomicLong(8682522807148012L);
public Random(long seed) {
if (getClass() == Random.class)
this.seed = new AtomicLong(initialScramble(seed));
else {
// subclass might have overriden setSeed
this.seed = new AtomicLong();
setSeed(seed);
}
}
private static long initialScramble(long seed) {
return (seed ^ multiplier) & mask;
}
。。。```
```java.util.concurrent.atomic.AtomicLong
public final boolean compareAndSet(long expect,
long update)
Atomically sets the value to the given updated value if the current value == the expected value.
Parameters:
expect - the expected value
update - the new value
Returns:
true if successful. False return indicates that the actual value was not equal to the expected value.```

1、获得一个长整形数作为“初始种子”（系统默认的是8682522807148012L）

2、不断与一个变态的数——181783497276652981L相乘（天知道这些数是不是工程师随便滚键盘滚出来的-.-）直到某一次相乘前后数值相等

3、与系统随机出来的nanotime值作异或运算，得到最终的种子

```    public int nextInt() {
return next(32);
}```

```    protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get();
} while (!seed.compareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits));
}```

OK,祝贺一下怎么样，因为我们已经深入到的线性同余法的核心了——没错，就是这几行代码！

Xn+1 = (a*Xn+c)(mod m)

m>0,0<a<m,0<c<m

1. c和m互素;

2. a-1可被所有m的质因数整除;

3. 当m是4的整数倍，a-1也是4的整数倍时，周期为m。所以m一般都设置的很大，以延长周期。

`nextseed = (oldseed * multiplier + addend) & mask;`

```    private static final long multiplier = 0x5DEECE66DL;
private static final long addend = 0xBL;
private static final long mask = (1L << 48) - 1;```

x对于2的N次幂取余，由于除数是2的N次幂，如：

0001，0010，0100，1000。。。。

13 = 1101    8 = 1000

13 / 8 = 1.101，所以小数点右侧的101就是余数，化成十进制就是5

0000，0001，0011，0111，01111，011111。。。

a & 1 = a,  a & 0 = 0

1、所有比2^N位（包括2^N那一位）全都为0

2、所有比2^N低的位保持原样

1101 % 1000 = 0101    1101 & 0111 = 0101

```    public int nextInt(int n) {
if (n <= 0)
throw new IllegalArgumentException("n must be positive");

if ((n & -n) == n)  // i.e., n is a power of 2
return (int)((n * (long)next(31)) >> 31);

int bits, val;
do {
bits = next(31);
val = bits % n;
} while (bits - val + (n-1) < 0);
return val;
}```

2 ：0000 0010      -2 ：1111 1110

8 ：0000 1000      -8 ：1111 1000

18 ：0001 0010     -18 ：1110 1110

20 ：0001 0100     -20 ：1110 1100

n & (n-1) == 0

Xn+1=（a*Xn ）(mod m ）

Yn = Xn/m

http://www.myexception.cn/program/1609435.html

## 从Java源码看String的两种比较方式

String的两种字符串比较方式 == 和 equals方法 ==: ==比较的是字符串在内存中的地址 代码示例: 1 public class EqualsDemo { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 String s1 = "String"; 8 String s2 = "String"; 9 String s3 = new String(&quo