C++ 中的随机数与 Python3 numpy.random.rand 计算的随机数相同

Mad*_*ent 8 c++ python random

我想在 C++ 中重复对 Python3 中已经实现的一些代码的测试,这些代码依赖于numpy.random.randrandn值以及特定的种子(例如seed = 1)。

我知道Python的随机实现是基于梅森扭曲器的。C++ 标准库也在std::mersenne_twister_engine.

C++ 版本返回无符号 int,而 Python rand 是浮点值。

有没有办法在 C++ 中获得与 Python 中生成的值相同的值,并确保它们相同?randn对于由?生成的数组也是如此

fde*_*hin 5

对于整数值,您可以这样做:

import numpy as np

np.random.seed(12345)
print(np.random.randint(256**4, dtype='<u4', size=1)[0])
Run Code Online (Sandbox Code Playgroud)
#include <iostream>
#include <random>

int main()
{
    std::mt19937 e2(12345);
    std::cout << e2() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

两个片段的结果都是 3992670690


通过查看源代码rand您可以通过以下方式在 C++ 代码中实现它:

import numpy as np

np.random.seed(12345)
print(np.random.rand())
Run Code Online (Sandbox Code Playgroud)
#include <iostream>
#include <iomanip>
#include <random>

int main()
{
    std::mt19937 e2(12345);
    int a = e2() >> 5;
    int b = e2() >> 6;
    double value = (a * 67108864.0 + b) / 9007199254740992.0;
    std::cout << std::fixed << std::setprecision(16) << value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

两个随机值都是 0.9296160928171479


使用起来会很方便std::generate_canonical,但是它使用了另一种方法将梅森扭曲器的输出转换为双倍。它们不同的原因可能是generate_canonical比 NumPy 中使用的随机生成器更加优化,因为它避免了昂贵的浮点运算,尤其是乘法和除法,如源代码所示。然而,它似乎依赖于实现,而 NumPy 在所有平台上都会产生相同的结果。

double value = std::generate_canonical<double, std::numeric_limits<double>::digits>(e2);
Run Code Online (Sandbox Code Playgroud)

这不起作用并产生结果 0.8901547132827379,这与 Python 代码的输出不同。