蒙特卡洛模拟计算期望值
作者:yunjinqi   类别:    日期:2024-06-07 22:27:14    阅读:663 次   消耗积分:0 分    

假设有一副54张牌的扑克,每次有放回的抽取一张,当每张牌都至少抽取一次之后总的抽取次记为x, 求x的期望值


蒙特卡洛模拟python版本:

import random
import time

begin_time = time.perf_counter()

result_num = []

cards_num = list(range(54))

for i in range(1000000):
    result = []
    count = 0
    while len(result) < 54:
        num = random.choice(cards_num)
        if num not in result:
            result.append(num)
        count += 1
    result_num.append(count)
end_time = time.perf_counter()
print("运算耗费的时间为:{}".format(end_time - begin_time))
print("平均期望为:{}".format(sum(result_num)/len(result_num)))

运算耗费的时间为:440.74856580002233

平均期望为:247.005991


蒙特卡洛模拟c++版本:

#include <iostream>
#include <vector>
#include <algorithm>
#include <random>
#include <numeric>
#include <chrono>

int main() {
    // 获取起始时间点
    auto start = std::chrono::high_resolution_clock::now();
    std::vector<int> result_num;
    std::vector<int> cards_num(54);
    std::iota(cards_num.begin(), cards_num.end(), 0);  // Fill with numbers from 0 to 53

    // Random number generator
    std::random_device rd;
    std::mt19937 gen(rd());

    for (std::size_t i = 0; i < 1000000; ++i) {
        std::vector<int> result;
        result.reserve(54); // Reserve space for 54 cards
        int count = 0;

        while (result.size() < 54) {
            std::uniform_int_distribution<> dis(0, 53);
            int num = dis(gen);
            //std::cout << "num = " << num << std::endl;

            if (std::find(result.begin(), result.end(), num) == result.end()) {
                result.push_back(num);
            }
            ++count;
        }
        result_num.push_back(count);
    }

    // Calculate the average
    double sum = std::accumulate(result_num.begin(), result_num.end(), 0LL);
    double average = sum / result_num.size();
    // 获取结束时间点
    auto end = std::chrono::high_resolution_clock::now();

    // 计算耗时
    std::chrono::duration<double> duration = end - start;

    // 输出耗时,单位为秒
    std::cout << "Function execution time: " << duration.count() << " seconds" << std::endl;

    std::cout << "average : " << average << std::endl;

    return 0;
}

Function execution time: 78.02 seconds

average : 247.033


c++版本只有python版本的5-6倍,看起来c++版本写的效率不怎么高。


chatgpt的答案:

image.png

image.png

然后我们乘以54:

E(T54)=54×4.565≈246.51

因此,所有54张牌至少被抽取一次所需的抽取次数的期望值大约是 246.51 次。

总结

在有放回地抽取54张牌,直到每张牌都至少被抽取一次的情况下,总的抽取次数的期望值约为 246.51 次。


版权所有,转载本站文章请注明出处:云子量化, http://www.woniunote.com/article/394
上一篇:蒙特卡洛模拟计算圆周率(python、java、cpp三个版本对比02)
下一篇:pybind文档1:如何安装pybind11