如何解决Python中极小概率下二项式概率计算返回0的问题?
解决旧版SciPy中低概率密码猜测成功率的计算精度问题
当使用SciPy 1.10.1版本计算小概率场景下的密码猜测成功率时(比如12位小写字母密码,单次猜测概率极低),直接调用1 - binom.pmf(k=0, n=..., p=...)会返回0.0,这是因为浮点数计算下溢导致(1-p)^n被舍入为0。以下是几种解决方法:
方法1:升级SciPy到最新版本
如补充说明所述,SciPy 1.11.2及以上版本已经修复了这个精度问题,直接使用原有代码即可得到正确结果:
from scipy.stats import binom (1 - binom.pmf(k=0, n=1000000000*3600, p=1 / 26**12))
方法2:使用泊松近似公式
当n极大、p极小时,二项分布的0次成功概率(1-p)^n可以用泊松近似e^(-n*p)来替代,该公式不会出现浮点数下溢问题,计算精度足够:
import math # 总猜测次数:1小时=3600秒,每秒10亿次 total_guesses = 1000000000 * 3600 # 单次猜测成功的概率:12位小写字母总可能数为26^12 single_prob = 1 / 26**12 # 计算成功概率 success_prob = 1 - math.exp(-total_guesses * single_prob) print(success_prob) # 输出约3.77e-5,即0.00377%
方法3:通过对数计算精确值
如果需要更精确的结果,可以先计算(1-p)^n的对数,再取指数避免下溢:
import math total_guesses = 1000000000 * 3600 single_prob = 1 / 26**12 # 计算0次成功的概率的对数,再转为指数 log_zero_success = total_guesses * math.log(1 - single_prob) zero_success_prob = math.exp(log_zero_success) success_prob = 1 - zero_success_prob print(success_prob)
该方法的结果与泊松近似几乎一致,因为当p极小时,math.log(1-p)近似等于-p,两者的误差可以忽略。
内容的提问来源于stack exchange,提问作者Gh0stFish
相关产品推荐
相关产品推荐

