gpt4 book ai didi

java - 线性同余生成器给出错误的输出

转载 作者:行者123 更新时间:2023-12-04 08:11:43 26 4
gpt4 key购买 nike

我创建了一个线性同余生成器 (LCG),但它似乎给了我错误的输出。

// Instance variables 
private long currentRandomNumber;
private long a;
private long c;
private long m;

public static void main(String[] args) {
// perform calculations and tests here
final long seed = 99L;

// Java's java.util.Random class values (according to Wikipedia):
long a = 25214903917L;
long c = 11L;
long m = 2^48L;

LCG lcg = new LCG(a, c, m, seed);

System.out.println("Sequence of LCG class: " + lcg.nextRandom() + ", " + lcg.nextRandom() + ", " + lcg.nextRandom() + ", " + lcg.nextRandom() + ", " + lcg.nextRandom());
}

public LCG(long seed, long a, long c, long m) {
currentRandomNumber = seed;
this.a = a;
this.c = c;
this.m = m;
}

// Implementation of the recurrence relation of the generator
public long nextRandom() {
currentRandomNumber = (a * currentRandomNumber + c) % m;
return currentRandomNumber;
}
我得到的输出是:
Sequence of LCG    class: 28, 61, 28, 61, 28
我使用了 a、c 和 m 的这些值,因为我读到 java.util.Random 类也使用这些值。但是使用具有相同种子的此类会给出不同的答案。我还检查了其他 lcg 计算器,我的答案也不符合这些。我不知道出了什么问题。

最佳答案

LCG 需要大模数
Linear congruential generator的 key 之一是m应该够大。或者,您可以快速找到重复的子序列,因为模运算总是为任何等差级数生成重复的子序列。但是,如果足够大,重复的子序列本身会很长,因此看起来不会重复。
您的

long m = 2^48L;
是 50。 ^不会做你期望的。它是 2 XOR 48而不是 2 的 48 次方。所以使用
long m = 1L << 48;  // or (long) Math.pow(2, 48)
反而。然后你会得到
Sequence of LCG    class: 2496275487794, 103243855293781, 72264694917948, -37076138618729, -26695784318378
为什么与 java.util.Random 不完全相同
根据我的经验,实现几乎总是带有启发式的。这是使用 OpenJDK 15 用于生成 nextInt 的那些启发式算法重新实现的代码。 eger 根据 openjdk /jdk15 .特别是根据 lines from 198 to 206 .
import java.lang.Math;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;

class LCG {
private AtomicLong currentRandomNumber;
//private long a;
//private long c;
//private long m;

private int bits = 32;
private long addend = 0xBL; // your `c` is here!
private long mask = (1L << 48) - 1; // your `m` is here!
private long multiplier = 0x5DEECE66DL; // your `a` is here!

public LCG(long seed, long a, long c, long m) {
currentRandomNumber = new AtomicLong((seed ^ multiplier) & mask);
//this.a = a;
//this.c = c;
//this.m = m;
}

public long nextRandom() {
long oldseed, nextseed;
AtomicLong seed = this.currentRandomNumber;
do {
oldseed = seed.get();
nextseed = (oldseed * multiplier + addend) & mask;
} while (!seed.compareAndSet(oldseed, nextseed));
return (int)(nextseed >>> (48 - bits)); // your `m` is here again
}
}

public class main {
public static void main(String[] args) {
long seed = 99L;

long a = 25214903917L;
long c = 11L;
long m = (long) Math.pow(2, 48);

LCG lcg = new LCG(seed, a, c, m);
Random random = new Random(seed);

System.out.println(lcg.nextRandom());
System.out.println(random.nextInt());
}
}

你会看到 lcg.nextRandom()random.nextInt()如果使用 OpenJDK 15 编译代码,则生成相同的整数。在重新实现时,我发现较旧的 OpenJDK 使用不同的启发式方法。

关于java - 线性同余生成器给出错误的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65921545/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com