我在Random class中看到了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
但上面的代码看起来并不相似。相反,它使用&amp;代替模数操作,如下线
nextseed =(oldseed * multiplier + addend)&amp;掩模;
有人可以帮我理解这种使用&amp; amp;和而不是模运算?
答案 0 :(得分:1)
使用2^n - 1
形式的掩码进行逐位AND运算与计算模数2^n
的结果相同:数字中任何1的高数都是2^n
的倍数,因此可以安全地丢弃。但请注意,如果使模数为2的幂(而不是2的幂减1),则某些乘数/加数组合非常差。该代码很好,但请确保它适合您的常量。
答案 1 :(得分:1)
如果mask + 1
是2的幂,则可以使用此方法。
例如,如果你想做模4,你可以写x & 3
而不是x % 4
来获得相同的结果。
但请注意,这需要x
为正号。