You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Monte Carlo模拟计算生日重合概率的Java程序问题排查与修复

蒙特卡洛生日概率模拟程序问题排查与修复

问题根源分析

原程序输入班级规模20、共享生日人数2时输出仅7%-8%,远低于预期的41%,核心错误有三个:

  • 数组初始化遗漏索引0:Collision方法中给生日数组赋值时,循环从i=1开始,导致数组第0位始终是默认值0,相当于第一个人的生日固定为1月1日,完全破坏了随机模拟的公平性。
  • 碰撞计数与判断逻辑不匹配需求:原方法返回的是所有生日相同的对数,而判断条件Collision(...)>=birthPpl要求对数大于等于指定人数。当需求是“至少2人共享生日”时,只要存在1对就满足条件,但原程序要求至少2对才计数,直接过滤了大部分符合条件的情况。
  • Random对象重复创建:每次调用Collision都新建Random实例,既影响随机性,也降低了模拟效率。

修复方案

  1. 修正生日数组的初始化循环,从i=0开始遍历所有元素,确保每个人的生日都是随机生成的。
  2. 重构碰撞检测逻辑:统计每个生日出现的次数,只要有任意一个生日的出现次数≥指定的共享人数,就判定为成功,不再统计对数。
  3. 复用Random实例,在主方法中创建一次,作为参数传入检测方法。

修复后的完整代码

import java.util.*;

public class MonteCarlo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入班级人数: ");
        int classSize = sc.nextInt();
        System.out.println("请输入共享生日的最少人数: ");
        int birthPpl = sc.nextInt();
        System.out.println("计算班级中至少" + birthPpl + "人共享同一生日的概率");

        sc.close();

        int simulations = 1000000;
        int success = 0;
        Random rand = new Random(); // 复用Random实例

        for (int i = 0; i < simulations; i++) {
            if (hasMatchingBirthday(classSize, birthPpl, rand)) {
                success++;
            }
        }

        double probability = (double) success / simulations * 100;
        System.out.printf("成功次数: %d, 总仿真次数: %d%n", success, simulations);
        System.out.printf("概率: %.2f%%%n", probability);
    }

    public static boolean hasMatchingBirthday(int classSize, int requiredCount, Random rand) {
        Map<Integer, Integer> birthdayCounts = new HashMap<>();

        for (int i = 0; i < classSize; i++) {
            int birthday = rand.nextInt(365);
            birthdayCounts.put(birthday, birthdayCounts.getOrDefault(birthday, 0) + 1);
            // 提前终止优化:一旦找到符合条件的生日,直接返回
            if (birthdayCounts.get(birthday) >= requiredCount) {
                return true;
            }
        }

        return false;
    }
}

修复说明

  • 用HashMap统计每个生日的出现次数,一旦某个生日的计数达到要求,直接返回true,提升了模拟效率。
  • 复用Random实例,保证随机性的同时减少对象创建开销。
  • 判断逻辑直接匹配需求:只要存在至少requiredCount人共享生日,就算一次成功,统计结果会符合预期(输入20和2时,结果约为41%)。

内容的提问来源于stack exchange,提问作者rimvoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 19:45:29