我试图在Python中重现一些涉及随机数生成的C代码。C代码使用MT19937生成器,如下所示:
#include <random>
#include <iostream>
int main() {
std::mt19937 generator(1234);
std::uniform_real_distribution<double> distribution(0.0, 1.0);
for (int i = 0; i < 10; ++i) {
std::cout << distribution(generator) << std::endl;
}
return 0;
}
字符串
Python版本是(NumPy 1.23.3)
import numpy as np
rng = np.random.Generator(np.random.MT19937(1234))
for _ in range(10):
print(rng.random())
型
在这两种情况下,随机种子都被设置为1234
。但在我的机器上(macOS 14.0 ARM),这两种情况产生不同的输出。
0.497664
0.817838
0.612112
0.77136
0.86067
0.150637
0.198519
0.815163
0.158815
0.116138
型
而Python代码输出
0.12038356302504949
0.4037014194964441
0.8777026256367374
0.9565788014497463
0.42646002242298486
0.28304326113156464
0.9009410688498408
0.830833142531224
0.6752899264264728
0.3977176012599666
型
为什么两个MT19937生成器产生不同的序列,尽管相同的种子?我如何(如果可能的话)使它们相同?
2条答案
按热度按时间ngynwnxp1#
梅森扭曲发生器对你给予的任何种子都有一个定义的序列。还有一些测试值可以用来验证你使用的发生器是否符合要求。
另一方面,分布是 * 非 * 标准化的,在不同的实现中可能会产生不同的值。删除分布以比较生成器。
还要注意的是,
std::mt19937
是一个32位的生成器,(对我来说)numpy版本是32位还是64位的生成器并不明显。你可能想把std::mt19937_64
和numpy实现进行比较-当然,仍然不涉及发行版。cnh2zyt32#
梅森扭转器引擎的C标准库版本与所有其他版本的不同之处在于如何从整数种子初始化状态。
你可以在C中使用另一个
mt19937
库来匹配numpy方法(我认为这是大多数人实现mt19937的方式),或者你可以改变Python引擎的种子匹配方式:个字符
这两种方法应该产生相同的输出:
型
现在,将这些32位数字转换为0和1之间的浮点数将有不同的结果,这取决于算法是如何实现的。你将不得不使用一些方法,这是标准化的给予相同的结果给定相同的随机数从梅森扭转。
(Also,
std::uniform_real_distribution<double> distribution(0.0, 1.0);
在不同的平台上不会给予相同的数字序列)或者,您可以使用
ctypes
或其他方式调用一小部分C++代码,这些代码只为您生成随机数,其余代码可以使用Python。