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
相关产品推荐
相关产品推荐

