我在Random类下看到Java中的LCG实现,如下所示:
/*
* This is a linear congruential pseudorandom number generator, as
* defined by D. H. Lehmer and described by Donald E. Knuth in
* <i>The Art of Computer Programming,</i> Volume 3:
* <i>Seminumerical Algorithms</i>, section 3.2.1.
*
* @param bits random bits
* @return the next pseudorandom value from this random number
* generator's sequence
* @since 1.1
*/
protected int next(int bits) {
long oldseed, nextseed;
AtomicLong seed = this.seed;
do {
oldseed = seed.get();
nextseed = (oldseed * multiplier + addend) & mask;
} while (!seed.compareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits));
}
但是下面的链接告诉我们LCG的形式应为x2 =(ax1 + b)modM
https://math.stackexchange.com/questions/89185/what-does-linear-congruential-mean
但是上面的代码看起来并不相似。相反,它使用&代替下面一行中的模运算
nextseed =(oldseed *乘数+加数)&mask;
有人可以帮助我了解使用&而不是取模运算的这种方法吗?
最佳答案
使用形式为2^n - 1
的掩码进行按位与运算与计算模2^n
的数字相同:数字中最高的任何1都是2^n
的倍数,因此可以安全地丢弃。但是请注意,如果将模数设为2的幂(而不是2的幂减去1),则某些乘数/加数组合的工作效果非常差。该代码很好,但是请确保它适合您的常量。