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,所以我输入了一个常量样本种子.我认为,这是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在这里不聪明?
解决方法
概率密度是分段线性的,由数组x和p以下列方式定义.构建了i = 0,…,N(其中N = x.size()-1)的点(x [i],p [i])的分段线性函数.然后将该函数归一化(通过将其除以其积分)以获得概率密度.
#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,1 / 20)和(40,0).这意味着在间隔[20,21 [我们可以期待f(20)*(21 – 20)= 1/20 * 1 = 1/20的结果.总共我们画出20万个价值,然后我们可以预期在[20,21]中有大约10,000点.
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
笔记:
>我截断了Visual Studio输出以更好地显示.对于[20,21 [20万*(0.5 *(f(20)f(21)))*(21 – 20)= 100,000 *(1/20 1/20 – 1) / 400)= 10,000-250 = 9750.