尝试将伯努利分布设置为函数输出时的 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。
我需要我的程序来模拟具有改变 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。