c++ - std::piecewise_linear_distribution 在 VS2012 下不工作?

标签 c++ visual-c++ random visual-studio-2012 c++11

我决定去了解 c++11 <random>更好,所以我写了这样一段代码:

std::mt19937 gen(10);
std::piecewise_linear_distribution<> d(Range.begin(), Range.end(),
                                       RangeValues.begin());

std::map<int, unsigned int> hist;
for (int n = 0; ++n != iterations;)
    ++hist[std::round(d(gen))];

for (auto p : hist)
   std::cout << std::setw(2) << p.first << ": "
             << std::string(p.second/(iterations/200), '*') << '\n';

出于某种原因std::random_device似乎在 Coliru 上不起作用,所以我输入了一个 const 样本种子。我猜想,它是 UB,因此 IIRC 它在很大程度上基于硬件,这就是 Coliru 不支持它的原因(如果我错了请纠正我)。但是在 Ideone 上它确实有效。

然后我将它移植到 VS2012 上运行,唯一的区别是自己实现了 std::round :

return number < 0.0 ? std::ceil(number - 0.5) : std::floor(number + 0.5);

它在 Coliru 上完全正确,但是当我在 VS2012 上编译并运行它时,the output is just wrong .

知道如何纠正这个问题,更重要的是,为什么会这样? 我是在做一些迟钝的事情,还是 VS2012 不是这里的聪明人?

最佳答案

这似乎是 Visual Studio 的问题。我尝试了下面的程序(改编自 OP),GCC 4.7.2、Clang 3.2 和 Intel 13.1.0 生成的输出非常合理,而 Visual Studio 2012 年 11 月 CTP 生成的输出完全不同。

概率密度是分段线性的,由数组 x 和 p 按以下方式定义。构建连接点 (x[i], p[i]) for i = 0, ..., N(其中 N = x.size() - 1)的分段线性函数。然后将该函数归一化(通过除以它的积分)得到概率密度。

#include <iostream>
#include <iomanip>
#include <string>
#include <random>
#include <array>

int main() {

    std::mt19937 gen(10);

    std::array<double, 3> x = {{0, 20, 40}};
    std::array<double, 3> p = {{0,  1,  0}};
    std::piecewise_linear_distribution<> dist(x.begin(), x.end(), p.begin());

    std::array<int, 40> hist = {{0}};

    for (size_t i = 0; i < 200000; ++i)
        ++hist[static_cast<size_t>(dist(gen))];

    for (size_t n = 0; n < hist.size(); ++n)
        std::cout << std::setfill('0') << std::setw(2) << n << ' ' << 
          std::string(hist[n] / 200, '*') << std::endl;

    std::cout << "\nValues in interval [20, 21[ : " << hist[20] << std::endl;
}

在我们的示例中,多边形函数连接 (0, 0)、(20, 1) 和 (40, 0)。因此,它的形状是一个等腰三角形,底边为 40,高为 1,面积为 20。因此,概率密度 f 连接 (0, 0)、(20, 1/20) 和 (40, 0)。这意味着在区间 [20, 21[ 中,我们可以预期 f(20) * (21 - 20) = 1/20 * 1 = 1/20 抽奖结果。我们总共绘制了 200,000 个值,然后我们可以预期 [20, 21[.

GCC、Clang 和 Intel 在 [20, 21[] 中报告了 9734 个点,并显示了一个与等腰三角形非常相似的模式:

00 *
01 ***
02 *****
03 ********
04 ***********
05 **************
06 ***************
07 ******************
08 ********************
09 ************************
10 **************************
11 ****************************
12 *******************************
13 *********************************
14 ***********************************
15 ***************************************
16 *****************************************
17 ******************************************
18 **********************************************
19 ************************************************
20 ************************************************
21 *********************************************
22 *******************************************
23 *****************************************
24 **************************************
25 ************************************
26 **********************************
27 ******************************
28 ****************************
29 **************************
30 ***********************
31 ********************
32 ******************
33 ****************
34 *************
35 ***********
36 *********
37 ******
38 ***
39 *

Values in interval [20, 21[ : 9734

不幸的是,Visual Studio 2012 年 11 月 CTP 给出了这个:

00 ********************************************** [truncated]
01 **********************************************
02 ***********************************
03 *****************************
04 **************************
05 ***********************
06 *********************
07 ********************
08 *******************
09 ******************
10 *****************
11 ****************
12 ***************
13 **************
14 **************
15 **************
16 *************
17 *************
18 *************
19 ************
20 ************
21 *************
22 *************
23 *************
24 *************
25 **************
26 ***************
27 ***************
28 ****************
29 *****************
30 ******************
31 *******************
32 *******************
33 *********************
34 ***********************
35 **************************
36 *****************************
37 ***********************************
38 **********************************************
39 ********************************************** [truncated]

Values in interval [20, 21[ : 2496

注意事项:

  1. 为了更好地显示,我截断了 Visual Studio 输出。
  2. 对于 [20, 21[ 中的点数更好的估计是 200,000 * (0.5 * (f(20) + f(21))) * (21 - 20) = 100,000 * (1/20 + 1/20 - 1/400) = 10,000 - 250 = 9750。

关于c++ - std::piecewise_linear_distribution 在 VS2012 下不工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16000299/

相关文章:

c++ - 为什么qmap使用skiplist而不是ob rb-tree?

c++ - 如果在编译时已知边缘条件,我该如何省略调用?

c++ - 包含来自新文件夹 "cannot open include file - no such file or directory"的头文件

python - scipy——如何从列表中随机提取数组

c++ - 如何在 Windows 上解析由 std::put_time ("%x") 创建的字符串?

c++ - 计算圆的顶点

visual-c++ - 如何检查从 VC++ 生成的二进制 exe 的运行时库类型

JavaScript 条件回调

java - 在给定范围内用Java生成随机小写字母

c++ - Direct3D11 只渲染线条,而且顺序很奇怪