Park-Miller-Carta PRNG随机发生器总是返回2.33E-10

时间:2009-04-15 02:58:12

标签: java actionscript-3 random

我正在尝试使用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的响应。

4 个答案:

答案 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;

是你真正拥有的。这是你的意思吗?