尝试将伯努利分布设置为函数输出时的 C++ 问题

C++ Problem when trying to set bernoulli distribution as an output for function

我需要我的程序来模拟具有改变 p 能力的 bernoulli (p) 随机变量。 如果我这样写

#include <random>
#include <iostream>
#include <chrono>
int main()
{
double prob = 0.1; //let it be const for now, no need to change it in this example
std::mt19937 gen(std::chrono::steady_clock::now().time_since_epoch().count());
std::bernoulli_distribution coin(prob);

int success = 0;
for (int i = 0; i < 1000; ++i) {
  if (coin(prob)) ++success;
}
  std::cout << success << "\n";
    
  return 0;
}

它工作得很好。但是我需要更改参数 p,所以我决定创建一个函数,该函数采用一些切换器,根据切换器模拟具有参数的随机变量,以及 returns true 或 false。 这是我的代码:

#include <random>
#include <iostream>
#include <chrono>

 bool coin_flip(int switcher) {
   double prob;
      switch (switcher) {
      case 1: {
    prob = 0.1;
    std::mt19937 gen(std::chrono::steady_clock::now().time_since_epoch().count());
    std::bernoulli_distribution coin(prob);
    return coin(gen);
      }
      case 2: {
    prob = 0.2;
    std::mt19937 gen(std::chrono::steady_clock::now().time_since_epoch().count());
    std::bernoulli_distribution coin(prob);
    return coin(gen);
      }

      }
    }
int main()
{
    int success = 0;
    
    for (int i = 0; i < 1000; ++i) {
      if (coin_flip(1)) {
    ++success;
      }
    }

    std::cout << success << "\n";
    
    return 0;
}

主体中的 for 循环计算 1000 次尝试中的成功次数,我预计它会在 100 次左右,但我确实得到了奇怪的结果。太多零和大数字。

所以我的问题是为什么 coin(prob) 在传递到函数的输出时会中断?

此外,如果您有好的想法,我将不胜感激任何关于如何模拟具有不同参数 p 的伯努利 r.v 序列的建议(例如,我们处于 p 取决于计数器的循环中一)

感谢您的宝贵时间

您不应该为每次掷骰都创建一个新的随机数生成器,这会破坏整个伪随机性。

创建一个全局(-ish)生成器并在每个函数调用中重用它:

bool coin_flip(int switcher) {
    static std::mt19937 gen(std::chrono::steady_clock::now().time_since_epoch().count());

    switch(switcher)
    {
        case 1:
            std::bernoulli_distribution coin(0.1);
            return coin(gen);
        case 2:
            std::bernoulli_distribution coin(0.2);
            return coin(gen);
    }
    throw std::invalid_argument{"Incorrect switcher value"};
}

static 局部变量仅在第一次函数调用期间初始化一次,并且在所有其他函数调用中保持可访问性。它们在生命周期方面是全局的(它们只会在程序结束时消失),但只能从此函数内访问。

您可以创建一个 Coin class 以给定概率保存特定分布,然后将其多个实例存储在一个容器中

#include <random>
#include <iostream>
#include <vector>

template< class Dist >
class Coin
{
    Dist dist_;

  public:
    Coin(double p) : dist_{p} {}

    template< class Gen >
    bool toss(Gen& gen) { return dist_(gen); }
};

int main()
{
    std::seed_seq ss{ 42, 987654321, 17, 65535 };
    std::mt19937 gen{ ss };

    using coin_t = Coin<std::bernoulli_distribution>;

    std::vector<coin_t> coins{
        0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9
    };

    std::vector<int> successes(coins.size());
    
    for (size_t i = 0; i < 1000; ++i) {
        for (size_t c = 0; c < coins.size(); ++c) {
            successes[c] += coins[c].toss(gen);
        }
    }

    for (auto s : successes) {
        std::cout << s << '\n';
    }
}

可测试here