生日问题代码返回69.32%而非预期50.05%的问题排查
生日问题代码错误排查与修正
错误原因
你的代码采用了「组合数 × 单组同生日概率」的计算方式,但这种方法会重复统计存在多组同生日的情况。比如当有3个人生日相同时,会被计算3次(每一对的组合),最终导致概率结果被高估。
正确解法思路
生日问题的标准解法是通过补集计算:先算出「所有人生日都不重复」的概率,再用1减去这个值,得到「至少有两人生日相同」的概率。
公式推导:
- 第1个人生日无限制:概率为
365/365 - 第2个人生日与第1人不同:概率为
364/365 - 第3个人生日与前2人不同:概率为
363/365 - ...
- 第n个人生日与前n-1人不同:概率为
(365 - n + 1)/365 - 所有人生日唯一的概率 = 上述所有概率的乘积
- 至少两人生日相同的概率 =
1 - 所有人生日唯一的概率
修正后的完整代码
JavaScript 部分
function doProbability() { const cntPeople = document.getElementById('setSize').valueAsNumber; const cntSubset = document.getElementById('subsetSize').valueAsNumber; // 仅处理子集大小为2的情况(标准生日问题) if (cntSubset !== 2) { document.getElementById('result').textContent = "当前仅支持计算至少两人生日相同的概率,请将subsetSize设为2"; return; } const prob = getProbability(cntPeople); const probAsPercentage = prob.toLocaleString(undefined, { style: 'percent', minimumFractionDigits: 2 }); document.getElementById('result').textContent = "Probability: " + probAsPercentage; } function getProbability(cntPeople) { if (cntPeople <= 1) return 0; // 计算所有人生日都不重复的概率 let uniqueProb = 1; for (let i = 0; i < cntPeople; i++) { uniqueProb *= (365 - i) / 365; } // 返回至少两人生日相同的概率 return 1 - uniqueProb; }
CSS 部分
label { display: block; }
HTML 部分
<label> Size of entire set of people <input type="number" min="1" max="999" value="23" id="setSize" /> </label> <label> Size of small subset of people <input type="number" min="1" max="999" value="2" id="subsetSize" /> </label> <button onclick="doProbability()">Click me</button> <br /> <output id="result"></output>
验证结果
当setSize设为23时,修正后的代码会返回约50.73%,完全符合生日问题的理论值。
内容的提问来源于stack exchange,提问作者Node.JS
相关产品推荐
相关产品推荐

