C 11交叉编译器/标准库随机分布的可重复性
发布时间:2020-12-16 06:53:08 所属栏目:百科 来源:网络整理
导读:虽然随机引擎需要在每个编译器上给出相同的数字序列.至少一些随机分布不是,只要求它们满足统计和概率阈值.举个例子: #include random#include iostreamint main() { std::mt19937 foo; std::uniform_int_distributionint bar(0,1000); for (int i=0; i99; +
虽然随机引擎需要在每个编译器上给出相同的数字序列.至少一些随机分布不是,只要求它们满足统计和概率阈值.举个例子:
#include <random> #include <iostream> int main() { std::mt19937 foo; std::uniform_int_distribution<int> bar(0,1000); for (int i=0; i<99; ++i) { bar(foo); } std::cout << bar(foo) << std::endl; return 0; } 在针对libc编译时,对于(我的版本)libstdc和89编译时,将打印808. 无论您给出的合规环境如何,哪些标准提供的分配功能(如果有)可以保证产生一致的结果? 解决方法
不幸的是,从N3936(C 14最终草案)开始,没有标准提供的随机分布有这样的要求.而且很容易理解为什么.编写分布函数有许多有效的方法.有些比其他人好.甚至像正常分布一样基本的算法也越来越好,并且是积极研究的主题.强制使用单个算法将不必要地阻碍未来算法的实施.
幸运的是,你可以写自己的.各种分发类的标头规范位于第26.5.8节.但是没有理由为什么你的需要必须遵循这种结构. (请注意,我没有彻底测试过这段代码,并且某些引擎可能存在不良行为,或者溢出,但我已经采取了一些措施来避免后者,这更多是作为说明性示例而不是规范来源令人敬畏的统一分布.话虽这么说,如果你发现它有什么问题,请在评论中告诉我,我会很乐意纠正它.) #include <random> #include <tuple> #include <iostream> template<class IntType = int> class my_uniform_int_distribution { public: // types typedef IntType result_type; typedef std::pair<int,int> param_type; // constructors and reset functions explicit my_uniform_int_distribution(IntType a = 0,IntType b = std::numeric_limits<IntType>::max()); explicit my_uniform_int_distribution(const param_type& parm); void reset(); // generating functions template<class URNG> result_type operator()(URNG& g); template<class URNG> result_type operator()(URNG& g,const param_type& parm); // property functions result_type a() const; result_type b() const; param_type param() const; void param(const param_type& parm); result_type min() const; result_type max() const; private: typedef typename std::make_unsigned<IntType>::type diff_type; IntType lower; IntType upper; }; template<class IntType> my_uniform_int_distribution<IntType>::my_uniform_int_distribution(IntType a,IntType b) { param({a,b}); } template<class IntType> my_uniform_int_distribution<IntType>::my_uniform_int_distribution(const param_type& parm) { param(parm); } template<class IntType> void my_uniform_int_distribution<IntType>::reset() {} template<class IntType> template<class URNG> auto my_uniform_int_distribution<IntType>::operator()(URNG& g) -> result_type { return operator()(g,param()); } template<class IntType> template<class URNG> auto my_uniform_int_distribution<IntType>::operator()(URNG& g,const param_type& parm) -> result_type { diff_type diff = (diff_type)parm.second - (diff_type)parm.first + 1; if (diff == 0) // If the +1 overflows we are using the full range,just return g() return g(); diff_type badDistLimit = std::numeric_limits<diff_type>::max() / diff; do { diff_type generatedRand = g(); if (generatedRand / diff < badDistLimit) return (IntType)((generatedRand % diff) + (diff_type)parm.first); } while (true); } template<class IntType> auto my_uniform_int_distribution<IntType>::a() const -> result_type { return lower; } template<class IntType> auto my_uniform_int_distribution<IntType>::b() const -> result_type { return upper; } template<class IntType> auto my_uniform_int_distribution<IntType>::param() const -> param_type { return {lower,upper}; } template<class IntType> void my_uniform_int_distribution<IntType>::param(const param_type& parm) { std::tie(lower,upper) = parm; if (upper < lower) throw std::exception(); } template<class IntType> auto my_uniform_int_distribution<IntType>::min() const -> result_type { return lower; } template<class IntType> auto my_uniform_int_distribution<IntType>::max() const -> result_type { return upper; } int main() { std::mt19937 foo; my_uniform_int_distribution<int> bar(0,1000); for (int i=0; i<99; ++i) { bar(foo); } std::cout << bar(foo) << std::endl; return 0; } 此代码在我测试的所有平台上打印出490. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |