0

我需要我的程序来模拟能够改变 p 的伯努利 (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,所以我决定创建一个函数,它需要一些切换器,根据切换器模拟带有参数的随机变量,并返回 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 模拟伯努利 rv 序列的任何建议(例如,我们处于一个循环中,其中 p 取决于计数器 i)

感谢您的时间

4

2 回答 2

1

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

创建一个全局(-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局部变量仅在第一次函数调用期间初始化一次,并且在每个其他函数调用中保持可访问性。它们的生命周期是全局的(它们只会在程序结束时消失),但只能从这个函数中访问。

于 2020-12-03T11:58:54.167 回答
1

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

#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';
    }
}

在这里测试。

于 2020-12-03T12:48:35.897 回答