6

我的任务是将一些 python 代码移植到 Scala 以进行研究。现在我使用 Apache Math3 公共库,但在使用 MersenneTwister 时遇到了困难。

在 Python 中:

SEED = 1234567890

PRIMARY_RNG = random.Random()
PRIMARY_RNG.seed(SEED)
n = PRIMARY_RNG.randrange((2**31) - 1) #1977150888

在斯卡拉:

val Seed = 1234567890
val PrimaryRNG = new MersenneTwister(Seed)
val n = PrimaryRNG.nextInt(Int.MaxValue) //1328851649

我在这里想念什么?两者都是 MersenneTwister 的,
并且Int.MaxValue = 2147483647 = (2**31) - 1

4

3 回答 3

3

Apache Commons Math 显然使用整数作为 randomness 的基本来源,尽管我不太确定它是如何提取它的,而 Python使用由算法的 C 版本生成的双精度数

种子值的处理方式也可能存在差异,但由于它们甚至不会以相同的方式读取位,因此即使底层的伪随机生成器相同,也不会期望它们具有可比性。

于 2014-08-04T21:10:00.630 回答
2

正如我已经在评论中发布的那样,获取下一个整数的主要算法在 Python 和 Apache Math 之间是相同的(源代码在这里这里这里)。跟踪代码似乎主要区别在于两个版本如何为生成器提供种子。Python 版本会将给定的种子转换为数组并从数组中生成种子,而 Apache Math 版本有一个单独的算法用于从单个数字播种。因此,为了让 Apache MathnextInt(...)方法以保存方式作为 Pythonrandrange(...)方法运行,您应该使用数组为 Apache Math 版本播种。

(我不知道 Scala 所以下面的代码是在 Java 中)

MersenneTwister rng = new MersenneTwister();
rng.setSeed(new int[] {1234567890});
System.out.println(rng.nextInt(Integer.MAX_VALUE)); // 1977150888

另请注意,所有其他方法(例如random()vs. nextDouble())都是完全不同的,因此这种播种机制可能只会产生nextInt(...)randrange(...)返回相同的结果。

于 2014-08-05T13:18:19.583 回答
0

如果有人需要这样做,我在这里提出了一个基于CPython 实现的工作版本。

注意:如果用字符串做种子,random.seed()在 Python 2 和 3 之间切换。pythonStringHash这里的函数兼容 Python 2 版本,或者在 Python 3 中,random.seed(s, version=1).

private static long pythonStringHash(String s) {
  char[] chars = s.toCharArray();
  long x;
  if (s.isEmpty()) {
    x = 0;
  } else {
    x = chars[0] << 7;
  }

  for (char c : chars) {
    x = ((1000003 * x) ^ c);
  }

  x ^= chars.length;
  if (x == -1) {
    return -2;
  }
  return x;
}

private static void pythonSeed(MersenneTwister random, long seed) {
  int[] intArray;
  if (Long.numberOfLeadingZeros(seed) >= 32) {
    intArray = new int[] { (int) seed };
  } else {
    intArray = new int[] { (int) seed, (int) (seed >> 32) };
  }
  random.setSeed(intArray);
}

public static RandomGenerator pythonSeededRandom(String seed) {
  MersenneTwister random = new MersenneTwister();
  pythonSeed(random, pythonStringHash(seed));
  return random;
}

从那里, pythonSeededRandom("foo").nextDouble()应该等于 random.seed("foo"); random.random()

于 2019-01-11T06:21:22.167 回答