【问题标题】:Arriving at a close approximation of the probability using code使用代码得出概率的近似值
【发布时间】:2017-11-03 21:46:48
【问题描述】:

我收到了一道关于概率的数学题。它是这样的:

有 1000 张彩票,每张有 1000 张彩票。您决定每张彩票购买 1 张彩票。您至少赢得一个彩票的概率是多少?

我能够在纸上进行数学运算(到达 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;
}

现在,所有这些代码都输出相同的文本:

最终概率为=1
进程以退出代码 0 结束

似乎 rand() 函数在循环的所有 100000 次迭代中一直在输出相同的值。我无法解决这个问题。

我也尝试使用 randomize() 函数而不是 srand() 函数,但它似乎不起作用并给出了奇怪的错误,例如:

error: ‘randomize’ was not declared in this scope
randomize();
           ^

我认为 randomize() 在 C++ 的更高版本中已经停止使用。

我知道我在很多方面都错了。如果您能耐心地解释我的错误并告诉我一些可能的更正,我将不胜感激。

【问题讨论】:

    标签: c++ random probability discrete-mathematics


    【解决方案1】:

    您应该在外循环开始时重置您的计数 (p1)。另外,请注意最后的 integer 除法 p2/100000p2 的任何值

    看看你的代码的这个修改版本:

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

    典型的运行会输出如下内容:

    预期:0.632305 计算:0.63125

    【讨论】:

      【解决方案2】:

      请参阅this answer to someone else's question,了解有关伪随机数生成器工作原理的一般说明。

      这意味着您应该在程序中创建一个 PRNG 实例播种一次。不要在循环内或在多次调用的函数内执行这些任务,除非您真的知道自己在做什么并且正在尝试做一些复杂的事情,例如使用相关归纳策略,例如 common random numbers 或 @987654323 @实现“variance reduction”。

      【讨论】:

        【解决方案3】:

        仅在程序开始时通过srand 为伪随机数生成器播种一次。当您一遍又一遍地播种时,您会将伪随机数生成器重置为相同的初始状态。默认情况下,time 具有以秒为单位的粒度。您很有可能在一秒钟内完成所有 1000 次迭代 - 或者大部分迭代。

        【讨论】:

        • 我明白了,这就是我在第一个代码中尝试的。如何避免无法在同一循环中生成新随机数的问题?对于 x 和 y
        猜你喜欢
        • 2022-01-08
        • 1970-01-01
        • 2013-02-04
        • 2015-03-27
        • 2017-03-06
        • 2017-06-11
        • 2021-08-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多