用于生成均匀分布的随机比特集的方法

时间:2016-08-12 00:10:23

标签: c++ random bitset

如何生成长度为8的倍数的bitset(对应于标准数据类型),其中每个位为0或1且概率相等?

2 个答案:

答案 0 :(得分:2)

以下作品。

  • 选择具有良好统计特性的PRNG
  • 播种良好
  • 在包含范围内生成整数,包括整数类型的最小值和最大值。
  • 由于整数在整个范围内均匀分布,因此每个位表示必须是同等可能的。由于存在所有位表示,因此每个位都同样可以打开或关闭。

以下代码可以实现此目的:

#include <cstdint>
#include <iostream>
#include <random>
#include <algorithm>
#include <functional>
#include <bitset>

//Generate the goodness
template<class T>
T uniform_bits(std::mt19937& g){
  std::uniform_int_distribution<T> dist(std::numeric_limits<T>::lowest(),std::numeric_limits<T>::max());
  return dist( g );
}

int main(){
  //std::default_random_engine can be anything, including an engine with short
  //periods and bad statistical properties. Rather than cross my finers and pray
  //that it'll somehow be okay, I'm going to rely on an engine whose strengths
  //and weaknesses I know.
  std::mt19937 engine;

  //You'll see a lot of people write `engine.seed(std::random_device{}())`. This
  //is bad. The Mersenne Twister has an internal state of 624 bytes. A single
  //call to std::random_device() will give us 4 bytes: woefully inadequate. The
  //following method should be slightly better, though, sadly,
  //std::random_device may still return deterministic, poorly distributed
  //numbers.
  std::uint_fast32_t seed_data[std::mt19937::state_size];
  std::random_device r;
  std::generate_n(seed_data, std::mt19937::state_size, std::ref(r));
  std::seed_seq q(std::begin(seed_data), std::end(seed_data));
  engine.seed(q);

  //Use bitset to print the numbers for analysis
  for(int i=0;i<50000;i++)
    std::cout<<std::bitset<64>(uniform_bits<uint64_t>(engine))<<std::endl;

  return 0;
}

我们可以通过编译(g++ -O3 test.cpp)并使用以下内容执行某些统计来测试输出:

./a.out | sed -E 's/(.)/ \1/g' | sed 's/^ //' | numsum -c | tr " " "\n" | awk '{print $1/25000}' | tr "\n" " "

结果是:

1.00368 1.00788 1.00416 1.0036 0.99224 1.00632 1.00532 0.99336 0.99768 0.99952 0.99424 1.00276 1.00272 0.99636 0.99728 0.99524 0.99464 0.99424 0.99644 1.0076 0.99548 0.99732 1.00348 1.00268 1.00656 0.99748 0.99404 0.99888 0.99832 0.99204 0.99832 1.00196 1.005 0.99796 1.00612 1.00112 0.997 0.99988 0.99396 0.9946 1.00032 0.99824 1.00196 1.00612 0.99372 1.00064 0.99848 1.00008 0.99848 0.9914 1.00008 1.00416 0.99716 1.00868 0.993 1.00468 0.99908 1.003 1.00384 1.00296 1.0034 0.99264 1 1.00036

由于所有值都是&#34;关闭&#34;一方面,我们得出结论,我们的使命已经完成。

答案 1 :(得分:0)

这是一个很好的功能来实现这个目标:

template<typename T, std::size_t N = sizeof(T) * CHAR_BIT> //CHAR_BIT is 8 on most
                                                           //architectures
auto randomBitset() {
    std::uniform_int_distribution<int> dis(0, 1);
    std::mt19937 mt{ std::random_device{}() };

    std::string values;
    for (std::size_t i = 0; i < N; ++i)
        values += dis(mt) + '0';

    return std::bitset<N>{ values };
}