加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读