【问题标题】:Different pseudo random numbers between C++ and Python implementationsC++ 和 Python 实现之间的不同伪随机数
【发布时间】:2019-11-30 21:59:35
【问题描述】:

我正在尝试将 C++ 代码复制到 Python 3.6 中,但每个实现中的伪随机数序列都不同。两种实现的种子都是相同的,据我所知,两者都使用 Mersenne Twister 算法。

我做错了什么?

记住1:两个代码使用相同的种子

记住 2:据我所知,这两个代码都使用了实现相同算法 (Mersenne Twister) 的函数。

C++:

#include <random>
#include <iostream>
int main(int argc, char* argv[])
{  
    std::mt19937 gen(2);
    std::uniform_int_distribution<> dis(0, 61);

    for (int n=0; n<10; ++n)
        std::cout << dis(gen) << ' ';

    return 0;
}

Python 3.6:

import numpy as np
rng = np.random.RandomState(2)
for i in range(10):
    print(str(rng.randint(0, 62)))

注意:randint 有一个独占的上限。这就是为什么我在 C++ 代码上使用 61,而在 Python 代码上使用 62。

【问题讨论】:

  • 但是伪随机数的序列在每个实现中是不同的 -- 这不是一个特性而不是一个错误吗?
  • 据我所知,两种实现都使用相同的算法(Mersenne Twister)。这样,一旦种子相同,结果应该是相同的。
  • @thc 真的吗????这是我只在 Python 上得到的序列。我不明白,但我会三重检查:-)
  • 是的,我用过:g++ temp.cpp -o temp 然后./temp 输出40 15 45 8 22 43 18 11 40 7。编译器在 OS X 上很响。
  • 我的是 g++ (Ubuntu 7.4.0-1ubuntu1~18.04) 7.4.0,我真的不知道为什么它会给出不同的结果,但再次感谢你。

标签: python c++ random mersenne-twister


【解决方案1】:

您应该注意 C++ 的标准库发行版,包括 std::uniform_int_distribution,使用实现定义的算法。换句话说,这些实现可能会根据您选择的 C++ 库实现而改变,并且这些库将来可能会改变这些算法。 (这与 C++ 的 随机引擎 类形成对比,例如 std::mt19937,后者确实保证从同一个种子返回相同的伪随机值。)另见 this answer

您最好的做法是实现或找到 RNG 算法的稳定实现(例如我在 my article 中描述的算法)并实现他们提供的 transform the random numbers 方法。 (在为特定应用程序选择 RNG 时需要记住一些事项;我在此处链接的第一篇文章有​​更多信息。)

【讨论】:

  • 你没听懂他的回答。基本上他说,即使你使用了定义明确的mt19937std::uniform_int_distribution 也没有严格定义,所以即使在 C++ 形式的编译器到编译器,你也可以得到不同的结果。
  • @carlosOst:您不仅使用了std::mt19937,还使用了std::uniform_int_distribution,这是实现定义的——它可能因C++标准库的实现而异。
  • 相当肯定 C++ 和 Python 也使用不同的规则来初始化 Mersenne Twister 状态(这是巨大的);在这两种情况下,您都可以将2 作为种子传递,但它会扩展到完全不同的内部状态,因此即使没有std::uniform_int_distribution 干扰,行为也会有所不同。不确定numpy的版本是否更类似于C++,但Python's built-in seed expansion algorithm is pretty different from what I can tell
【解决方案2】:

从 RNG 到单个有界 int 并没有一种独特的方法。例如:

http://www.pcg-random.org/posts/bounded-rands.html

它有几个版本。请注意,C++ 和 Python 在这里采用不同的选项,因此您会从“相同”的 RNG 和种子中获得不同的序列。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-23
    • 2021-04-30
    • 2012-02-05
    • 2021-04-12
    • 2017-12-24
    • 1970-01-01
    • 2013-01-08
    相关资源
    最近更新 更多