我正在尝试使用Park-Miller-Carta PRNG随机数生成器的Java实现。
以下是ActionScript 3 from here中随机函数的实现。
return (_currentSeed = (_currentSeed * 16807) % 2147483647) / 0x7FFFFFFF
+ 0.000000000233;
我没有太多运气在Java中工作:
int seed = 20; //for example.
public double random() {
seed = (seed * 16807) % 2147483647;
return seed / 0x7FFFFFFF + 0.000000000233;
}
这总是返回2.33E-10
。我在Java中做错了什么想法? (AS3代码返回0.0001565276181885122
,然后0.6307557630963248
返回前两个种子为20
的响应。
答案 0 :(得分:6)
seed / 0x7FFFFFFF
是整数运算,因为两个参数都是整数。整数除法总是向下舍入“真实”结果。在这种情况下,真实结果介于0和1之间,因此操作始终返回0.
要获得浮点结果,至少有一个参数必须是float,可以这样实现:
return (double)seed / 0x7FFFFFFF + 0.000000000233;
答案 1 :(得分:2)
好的,所以基本的问题是你需要做浮点除法,而不是其他人指出的整数除法。
但我认为修复这个特定的代码除了重点。为什么一开始就烦恼呢?它使用的是基本相同的算法类java.lang.Random!
如果您想要快速生成器,请考虑XORShift generator。如果你想要一个高质量的生成器,你有SecureRandom开箱即用(虽然速度要慢得多),考虑一下Numerical Recipes算法(一个相当快速的组合生成器),你可以用Java实现如下:
public class HighQualityRandom extends Random {
private Lock l = new ReentrantLock();
private long u;
private long v = 4101842887655102017L;
private long w = 1;
public HighQualityRandom() {
this(System.nanoTime());
}
public HighQualityRandom(long seed) {
l.lock();
u = seed ^ v;
nextLong();
v = u;
nextLong();
w = v;
nextLong();
l.unlock();
}
@Override
public long nextLong() {
l.lock();
try {
u = u * 2862933555777941757L + 7046029254386353087L;
v ^= v >>> 17;
v ^= v << 31;
v ^= v >>> 8;
w = 4294957665L * (w & 0xffffffff) + (w >>> 32);
long x = u ^ (u << 21);
x ^= x >>> 35;
x ^= x << 4;
return (x + v) ^ w;
} finally {
l.unlock();
}
}
protected int next(int bits) {
return (int) (nextLong() >>> (64-bits));
}
}
这是从我需要并发的一些代码中复制的;你原则上可以摆脱锁,或者只是使用常规同步。
如果你绝对坚持使用Park-Miller-Carta,我至少将它包装在一个Random子类中,让java.util.Random负责将int转换为double等 - 毕竟,这就是可扩展性面向对象语言的库是......
答案 2 :(得分:1)
替换:
return seed / 0x7FFFFFFF+0.000000000233;
使用:
return (double)seed / 0x7FFFFFFF+0.000000000233;
答案 3 :(得分:0)
运营商优先权。
(seed / 0x7FFFFFFF)+0.000000000233;
是你真正拥有的。这是你的意思吗?