Visual Studio C++ 2012 和 2017 在随机数生成方面表现出不同的行为?
Visual Studio C++ 2012 & 2017 show different behaviour in random number generation?
我在 Visual Studio 2012(TC:11.0)和 Visual Studio 2017(TC:14.1)下使用以下代码片段从正态分布中抽取随机数:
#include "stdafx.h"
#include <iostream>
#include <random>
#include <cmath>
int main()
{
std::mt19937 e1;
std::mt19937 e2;
std::normal_distribution<> normal_dist(0, 1);
for (int n = 0; n<10; ++n) {
std::cout << "seq=" << e1();
std::cout << "; PRN=" << normal_dist(e2);
std::cout << std::endl;
}
return 0;
}
在 VS12 (TC: 11.0) 下,我收到以下结果:
seq=3499211612; PRN=0.253161
seq=581869302; PRN=-0.293219
seq=3890346734; PRN=0.0845901
seq=3586334585; PRN=-0.0570855
seq=545404204; PRN=0.992328
seq=4161255391; PRN=-1.43822
seq=3922919429; PRN=-0.910655
seq=949333985; PRN=0.106847
seq=2715962298; PRN=-0.600247
seq=1323567403; PRN=-0.844453
同样,在 VS17 (TC: 14.1) 下我得到
seq=3499211612; PRN=-0.146382
seq=581869302; PRN=0.13453
seq=3890346734; PRN=-1.87138
seq=3586334585; PRN=0.46065
seq=545404204; PRN=-0.214253
seq=4161255391; PRN=0.163712
seq=3922919429; PRN=-0.827944
seq=949333985; PRN=0.298595
seq=2715962298; PRN=1.05547
seq=1323567403; PRN=0.0102154
据我了解,序列生成是独立于工具链的,而正态分布采样则不是。这种工具链依赖性的原因是什么?
非常感谢!
显然 Microsoft 更改了随机包含中的一些实现。当在某个点从分布中抽取随机数时,需要均匀分布样本。在工具链 14.1 下,此任务的代码是:
_NRAND(_Eng, _Ty)
正如我发现的那样,Visual Studio 2012 年的工具链 11.0 和 Visual Studio 2017 年的工具链 14.1 展示了宏 _NRAND
的不同实现。该宏的目的是将从 PRN 引擎 _Eng
中提取的整数值序列映射到区间 [0, 1) 上。实现上的区别如下:
- 在 Visual Studio 2012 下,通过减去序列的最小值并除以其最大值和最小值的差值,以直接的方式重新调整序列的每个值。
- 下 Visual Studio 2017
_NRAND
调用函数 generate_canonical
。有关实现的详细信息,请随机查看第 282 行。它实际上做的是计算序列的多个重新缩放元素的某种多项式平均值。
我在 Visual Studio 2012(TC:11.0)和 Visual Studio 2017(TC:14.1)下使用以下代码片段从正态分布中抽取随机数:
#include "stdafx.h"
#include <iostream>
#include <random>
#include <cmath>
int main()
{
std::mt19937 e1;
std::mt19937 e2;
std::normal_distribution<> normal_dist(0, 1);
for (int n = 0; n<10; ++n) {
std::cout << "seq=" << e1();
std::cout << "; PRN=" << normal_dist(e2);
std::cout << std::endl;
}
return 0;
}
在 VS12 (TC: 11.0) 下,我收到以下结果:
seq=3499211612; PRN=0.253161
seq=581869302; PRN=-0.293219
seq=3890346734; PRN=0.0845901
seq=3586334585; PRN=-0.0570855
seq=545404204; PRN=0.992328
seq=4161255391; PRN=-1.43822
seq=3922919429; PRN=-0.910655
seq=949333985; PRN=0.106847
seq=2715962298; PRN=-0.600247
seq=1323567403; PRN=-0.844453
同样,在 VS17 (TC: 14.1) 下我得到
seq=3499211612; PRN=-0.146382
seq=581869302; PRN=0.13453
seq=3890346734; PRN=-1.87138
seq=3586334585; PRN=0.46065
seq=545404204; PRN=-0.214253
seq=4161255391; PRN=0.163712
seq=3922919429; PRN=-0.827944
seq=949333985; PRN=0.298595
seq=2715962298; PRN=1.05547
seq=1323567403; PRN=0.0102154
据我了解,序列生成是独立于工具链的,而正态分布采样则不是。这种工具链依赖性的原因是什么?
非常感谢!
显然 Microsoft 更改了随机包含中的一些实现。当在某个点从分布中抽取随机数时,需要均匀分布样本。在工具链 14.1 下,此任务的代码是:
_NRAND(_Eng, _Ty)
正如我发现的那样,Visual Studio 2012 年的工具链 11.0 和 Visual Studio 2017 年的工具链 14.1 展示了宏 _NRAND
的不同实现。该宏的目的是将从 PRN 引擎 _Eng
中提取的整数值序列映射到区间 [0, 1) 上。实现上的区别如下:
- 在 Visual Studio 2012 下,通过减去序列的最小值并除以其最大值和最小值的差值,以直接的方式重新调整序列的每个值。
- 下 Visual Studio 2017
_NRAND
调用函数generate_canonical
。有关实现的详细信息,请随机查看第 282 行。它实际上做的是计算序列的多个重新缩放元素的某种多项式平均值。