Java Park Miller Carta PRNG随机发生器allways返回2.33E-10
我正在尝试用Java实现Park Miller Carta PRNG随机数生成器 下面是ActionScript 3中随机函数的实现 我没有太多的运气让它在Java中工作:Java Park Miller Carta PRNG随机发生器allways返回2.33E-10,java,actionscript-3,random,Java,Actionscript 3,Random,我正在尝试用Java实现Park Miller Carta PRNG随机数生成器 下面是ActionScript 3中随机函数的实现 我没有太多的运气让它在Java中工作: int seed = 20; //for example. public double random() { seed = (seed * 16807) % 2147483647; return seed / 0x7FFFFFFF + 0.000000000233; } 这总是返回2.33E-10。你知道
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.630757630963248
,前两个响应的种子为20
)。替换:
return seed / 0x7FFFFFFF+0.000000000233;
与:
是一个整数运算,因为两个参数都是整数。整数除法总是向下舍入“真”结果。在这种情况下,真实结果介于0和1之间,因此操作始终返回0
要获得浮点结果,至少有一个参数必须是浮点,可以这样实现:
return (double)seed / 0x7FFFFFFF + 0.000000000233;
运算符优先级
(seed / 0x7FFFFFFF)+0.000000000233;
是你真正拥有的。这就是你的意思吗?好的,那么关键的问题是你需要做浮点除法,而不是像其他人指出的那样做整数除法 但我认为修复这个特定的代码有点超出了重点。为什么一开始就要麻烦它呢?它使用的基本上是同一类算法java.lang.Random
如果你想要一个快速生成器,考虑一个。如果你想要一个质量好的生成器,你就有了它(尽管它慢得多),考虑一下数字配方算法(一个相当快的组合发生器),你可以在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));
}
}
公共类HighQualityRandom扩展了Random{
private Lock l=新的可重入锁();
私人长u;
专用长v=41018428876551017L;
私人长w=1;
公共暴政(){
这个(System.nanoTime());
}
公共高质量暴政(长种子){
l、 锁();
u=种子^v;
nextLong();
v=u;
nextLong();
w=v;
nextLong();
l、 解锁();
}
@凌驾
公共长下长(){
l、 锁();
试一试{
u=u*286293355577941757L+7046029254386353087L;
v^=v>>>17;
v^=v>>8;
w=4294957665L*(w&0xffffffff)+(w>>>32);
长x=u^(u>>35;
x^=x>>(64位);
}
}
这是从我需要并发的代码中复制出来的;原则上可以去掉锁,或者只使用常规同步
如果您绝对坚持使用Park Miller Carta,我至少会将其包装在一个随机子类中,并让java.util.Random负责将int转换为double等——毕竟,这就是面向对象语言中的可扩展库的用途……为什么?如果这是为了您自己的启发,这是一件事,但对于生产代码来说确实是good(即加密安全)生成随机数非常困难。RNG可能是大多数密码系统中最大的技术漏洞。@Chris和Park Miller Carta相当糟糕。不,优先级规则可能不同。此外,除法运算符的语义可能不同,这似乎是已经发生的事。
return (double)seed / 0x7FFFFFFF + 0.000000000233;
(seed / 0x7FFFFFFF)+0.000000000233;
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));
}
}