使用代码得出概率的近似值
Arriving at a close approximation of the probability using code
给我一道关于概率的数学题。它是这样的:
There are 1000 lotteries and each has 1000 tickets. You decide to buy 1 ticket per lottery. What is the probability that you win at least one lottery?
我能够在纸上用数学方法做到这一点(达到 1 - (999/1000)^1000),但我想到了在我的计算机上进行随机实验的大量迭代的想法。所以,我输入了一些代码——确切地说是两个版本,但都出现了故障。
代码 1:
#include<iostream>
#include <stdlib.h>
using namespace std;
int main() {
int p2 = 0;
int p1 = 0;
srand(time(NULL));
for (int i = 0; i<100000; i++){
for(int j = 0; j<1000; j++){
int s = 0;
int x = rand()%1000;
int y = rand()%1000;
if(x == y)
s = 1;
p1 += s;
}
if(p1>0)
p2++;
}
cout<<"The final probability is = "<< (p2/100000);
return 0;
}
代码 2:
#include<iostream>
#include <stdlib.h>
using namespace std;
int main() {
int p2 = 0;
int p1 = 0;
for (int i = 0; i<100000; i++){
for(int j = 0; j<1000; j++){
int s = 0;
srand(time(NULL));
int x = rand()%1000;
srand(time(NULL));
int y = rand()%1000;
if(x == y)
s = 1;
p1 += s;
}
if(p1>0)
p2++;
}
cout<<"The final probability is = "<< (p2/100000);
return 0;
}
代码3(参考了一些进阶课文,但大部分都看不懂):
#include<iostream>
#include <random>
using namespace std;
int main() {
int p2 = 0;
int p1 = 0;
random_device rd;
mt19937 gen(rd());
for (int i = 0; i<100000; i++){
for(int j = 0; j<1000; j++){
uniform_int_distribution<> dis(1, 1000);
int s = 0;
int x = dis(gen);
int y = dis(gen);
if(x == y)
s = 1;
p1 += s;
}
if(p1>0)
p2++;
}
cout<<"The final probability is = "<< (p2/100000);
return 0;
}
现在,所有这些代码都输出相同的文本:
The final probability is = 1
Process finished with exit code 0
似乎 rand() 函数在循环的所有 100000 次迭代中一直输出相同的值。我没能解决这个问题。
我也试过使用 randomize() 函数而不是 srand() 函数,但它似乎不起作用并且会出现奇怪的错误,例如:
error: ‘randomize’ was not declared in this scope
randomize();
^
我认为 randomize() 已在更高版本的 C++ 中停用。
我知道我在很多层面上都错了。如果您能耐心地解释我的错误并让我知道一些可能的更正,我将不胜感激。
仅在程序开始时通过 srand
为伪随机数生成器播种一次。当你一遍又一遍地播种时,你将伪随机数生成器重置为相同的初始状态。 time
默认以秒为单位。您很有可能在一秒钟内完成所有 1000 次迭代(或其中的大部分迭代)。
有关伪随机数生成器工作原理的一般说明,请参阅 。
这意味着您应该 在您的程序中创建一个 PRNG 实例 并且 播种一次。不要在循环内或在多次调用的函数内执行这些任务,除非你真的知道你在做什么并且正在尝试做一些复杂的事情,例如使用相关归纳策略,例如 common random numbers or antithetic variates to achieve "variance reduction” .
您应该在外循环开始时重置计数 (p1
)。另外,请注意最后的 整数 除法 p2/100000
,任何 p2
< 100000 的值都会导致 0.
查看您的代码的修改版本:
#include <iostream>
#include <random>
int main()
{
const int number_of_tests = 100000;
const int lotteries = 1000;
const int tickets_per_lottery = 1000;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> lottery(1, tickets_per_lottery);
int winning_cases = 0;
for (int i = 0; i < number_of_tests; ++i )
{
int wins = 0; // <- reset when each test start
for(int j = 0; j < lotteries; ++j )
{
int my_ticket = lottery(gen);
int winner = lottery(gen);
if( my_ticket == winner )
++wins;
}
if ( wins > 0 )
++winning_cases;
}
// use the correct type to perform these calculations
double expected = 1.0 - std::pow((lotteries - 1.0)/lotteries, lotteries);
double probability = static_cast<double>(winning_cases) / number_of_tests;
std::cout << "Expected: " << expected
<< "\nCalculated: " << probability << '\n';
return 0;
}
典型的 运行 会输出如下内容:
Expected: 0.632305
Calculated: 0.63125
给我一道关于概率的数学题。它是这样的:
There are 1000 lotteries and each has 1000 tickets. You decide to buy 1 ticket per lottery. What is the probability that you win at least one lottery?
我能够在纸上用数学方法做到这一点(达到 1 - (999/1000)^1000),但我想到了在我的计算机上进行随机实验的大量迭代的想法。所以,我输入了一些代码——确切地说是两个版本,但都出现了故障。
代码 1:
#include<iostream>
#include <stdlib.h>
using namespace std;
int main() {
int p2 = 0;
int p1 = 0;
srand(time(NULL));
for (int i = 0; i<100000; i++){
for(int j = 0; j<1000; j++){
int s = 0;
int x = rand()%1000;
int y = rand()%1000;
if(x == y)
s = 1;
p1 += s;
}
if(p1>0)
p2++;
}
cout<<"The final probability is = "<< (p2/100000);
return 0;
}
代码 2:
#include<iostream>
#include <stdlib.h>
using namespace std;
int main() {
int p2 = 0;
int p1 = 0;
for (int i = 0; i<100000; i++){
for(int j = 0; j<1000; j++){
int s = 0;
srand(time(NULL));
int x = rand()%1000;
srand(time(NULL));
int y = rand()%1000;
if(x == y)
s = 1;
p1 += s;
}
if(p1>0)
p2++;
}
cout<<"The final probability is = "<< (p2/100000);
return 0;
}
代码3(参考了一些进阶课文,但大部分都看不懂):
#include<iostream>
#include <random>
using namespace std;
int main() {
int p2 = 0;
int p1 = 0;
random_device rd;
mt19937 gen(rd());
for (int i = 0; i<100000; i++){
for(int j = 0; j<1000; j++){
uniform_int_distribution<> dis(1, 1000);
int s = 0;
int x = dis(gen);
int y = dis(gen);
if(x == y)
s = 1;
p1 += s;
}
if(p1>0)
p2++;
}
cout<<"The final probability is = "<< (p2/100000);
return 0;
}
现在,所有这些代码都输出相同的文本:
The final probability is = 1 Process finished with exit code 0
似乎 rand() 函数在循环的所有 100000 次迭代中一直输出相同的值。我没能解决这个问题。
我也试过使用 randomize() 函数而不是 srand() 函数,但它似乎不起作用并且会出现奇怪的错误,例如:
error: ‘randomize’ was not declared in this scope
randomize();
^
我认为 randomize() 已在更高版本的 C++ 中停用。
我知道我在很多层面上都错了。如果您能耐心地解释我的错误并让我知道一些可能的更正,我将不胜感激。
仅在程序开始时通过 srand
为伪随机数生成器播种一次。当你一遍又一遍地播种时,你将伪随机数生成器重置为相同的初始状态。 time
默认以秒为单位。您很有可能在一秒钟内完成所有 1000 次迭代(或其中的大部分迭代)。
有关伪随机数生成器工作原理的一般说明,请参阅
这意味着您应该 在您的程序中创建一个 PRNG 实例 并且 播种一次。不要在循环内或在多次调用的函数内执行这些任务,除非你真的知道你在做什么并且正在尝试做一些复杂的事情,例如使用相关归纳策略,例如 common random numbers or antithetic variates to achieve "variance reduction” .
您应该在外循环开始时重置计数 (p1
)。另外,请注意最后的 整数 除法 p2/100000
,任何 p2
< 100000 的值都会导致 0.
查看您的代码的修改版本:
#include <iostream>
#include <random>
int main()
{
const int number_of_tests = 100000;
const int lotteries = 1000;
const int tickets_per_lottery = 1000;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> lottery(1, tickets_per_lottery);
int winning_cases = 0;
for (int i = 0; i < number_of_tests; ++i )
{
int wins = 0; // <- reset when each test start
for(int j = 0; j < lotteries; ++j )
{
int my_ticket = lottery(gen);
int winner = lottery(gen);
if( my_ticket == winner )
++wins;
}
if ( wins > 0 )
++winning_cases;
}
// use the correct type to perform these calculations
double expected = 1.0 - std::pow((lotteries - 1.0)/lotteries, lotteries);
double probability = static_cast<double>(winning_cases) / number_of_tests;
std::cout << "Expected: " << expected
<< "\nCalculated: " << probability << '\n';
return 0;
}
典型的 运行 会输出如下内容:
Expected: 0.632305 Calculated: 0.63125