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

C#多等级乐透彩票中奖概率计算代码修正求解

问题根源

现有代码无法正确计算二、三等奖概率,核心是两个逻辑错误:

  • 奖项对应的命中号码数写死为6/5/4,没有和实际单次抽取球数k做关联。通用规则下:I等奖为命中全部k个开奖号码,II等奖为命中k-1个,III等奖为命中k-2个,写死固定值会导致非6球抽取场景计算完全错误。
  • 中奖组合数计算错误:只有全中一等奖时,符合条件的中奖组合数为1;二、三等奖的中奖组合数需要用组合乘法计算:从k个开奖号码中选对m个的组合数 * 从剩余(n-k)个非开奖号码中选了(k-m)个的组合数,现有代码所有奖项都按1种中奖组合计算,自然结果错误。
概率计算正确公式

单注命中m个号码的中奖概率 = (符合条件的中奖组合数) / (全部投注组合数)
其中:

  • 全部投注组合数 = C(n, k) 即从n个球选k个的总组合数
  • 命中m个号码的中奖组合数 = C(k, m) * C(n - k, k - m)
    • C(k, m):从k个开奖号里选对m个的组合数
    • C(n - k, k - m):选的剩下k-m个号码都来自没开奖的n-k个号码的组合数
修正后完整代码
using System;

class LotteryOddsCalculator
{
    static void Main(string[] args)
    {
        int n = Convert.ToInt32(Console.ReadLine());
        int k = Convert.ToInt32(Console.ReadLine());
        string awardLevel = Console.ReadLine().Trim();
        int matchCount = GetMatchCount(awardLevel, k);
        
        if (matchCount == -1)
        {
            Console.WriteLine("输入的奖项等级无效");
            return;
        }
        if (matchCount < 0 || k - matchCount < 0 || n - k < k - matchCount)
        {
            Console.WriteLine("参数不合法");
            return;
        }

        decimal winProb = CalculateWinProbability(n, k, matchCount);
        Console.WriteLine(Math.Round(winProb, 10).ToString("0.0000000000"));
    }

    /// <summary>
    /// 获取对应奖项需要命中的号码数
    /// </summary>
    static int GetMatchCount(string awardLevel, int pickCount)
    {
        return awardLevel switch
        {
            "I" => pickCount,
            "II" => pickCount - 1,
            "III" => pickCount - 2,
            _ => -1
        };
    }

    /// <summary>
    /// 计算中奖概率
    /// </summary>
    static decimal CalculateWinProbability(int totalBall, int pickCount, int matchCount)
    {
        // 总组合数
        decimal totalCombs = Combination(totalBall, pickCount);
        // 中奖组合数 = C(pickCount, matchCount) * C(totalBall - pickCount, pickCount - matchCount)
        decimal winCombs = Combination(pickCount, matchCount) * Combination(totalBall - pickCount, pickCount - matchCount);
        return winCombs / totalCombs;
    }

    /// <summary>
    /// 计算组合数C(n,k)
    /// </summary>
    static decimal Combination(int n, int k)
    {
        // 边界处理
        if (k < 0 || k > n) return 0;
        if (k == 0 || k == n) return 1;
        // 利用组合数对称性C(n,k)=C(n,n-k),减少计算量
        k = Math.Min(k, n - k);
        decimal result = 1;
        // 边乘边除避免数值过大溢出,精度更高
        for (int i = 1; i <= k; i++)
        {
            result = result * (n - k + i) / i;
        }
        return result;
    }
}
代码修正说明
  • 重构了奖项命中数计算逻辑,不再写死6/5/4,而是根据实际抽取球数k动态计算,适配任意选球数场景。
  • 重写了组合数计算方法,放弃直接算大阶乘的逻辑,改用边乘边除的方式计算,既避免大数溢出,也比直接算阶乘精度更高。
  • 修正了中奖组合数的计算逻辑,严格按照超几何分布的概率公式计算二、三等奖的符合条件组合数。
  • 增加了输入合法性校验,避免非法输入导致程序崩溃。
  • 输出时固定格式化10位小数,避免出现小数位数不足的情况。
结果验证

针对你给出的参考场景(总球数40、单次抽5个、II等奖):

  • 按通用奖项规则,II等奖命中数为k-1=4个
  • 总投注组合数C(40,5)=658008
  • 符合条件的中奖组合数=C(5,4)C(35,1)=535=175
  • 最终概率=175/658008≈0.0002659542,和你给出的参考输出完全匹配。

注:原参考示例标注II等奖命中5个号码为笔误,命中5个为I等奖,对应概率约为0.0000015197,和给出的输出值不符。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 15:24:21