基于FIPS186-4的大素数生成函数Python实现精度问题求助
解决FIPS186-4附录B3.2.1中随机素数生成的精度问题
我太懂这种痛点了——处理2048位级别的大整数时,浮点数的精度限制简直是噩梦,尤其是在严格遵循FIPS标准的场景下,一点点精度误差都可能导致不符合规范。
问题根源
你遇到的p < sqrt(2)*(2**((nlen/2)-1))判断,核心问题在于:
sqrt(2)是无理数,用浮点数(哪怕是双精度)表示时必然存在精度损失- 当
nlen=2048时,2**((2048/2)-1) = 2^1023,这个数已经远超双精度浮点数的精确表示范围(双精度只能精确表示到2^53以内的整数),直接相乘会丢失大量有效位,导致判断结果完全不可靠
完美解决方案:用整数运算替代浮点数
我们可以把不等式做数学变形,完全规避浮点数:
原不等式:
p < sqrt(2) * 2^((nlen/2)-1)
因为两边都是正数,平方后不等号方向不变,得到:
p² < 2 * (2^((nlen/2)-1))²
化简右边:
2 * (2^(nlen-2)) = 2^(nlen-1)
所以最终可以用纯整数判断:p * p < 2 ** (nlen - 1)
Python支持任意精度的整数,这个运算完全不会有精度损失,结果绝对准确。
修改后的代码示例
import os def generate_random_prime(nlen=2048): half_len = nlen // 2 while True: # 生成half_len位的随机整数(注意byteorder要和你的需求一致) p = int.from_bytes(os.urandom(half_len // 8), byteorder='big') # 确保p是奇数(FIPS步骤要求,可选但推荐) p |= 1 # 步骤4.4的判断:用整数平方替代浮点数运算 threshold_squared = 2 ** (nlen - 1) if p * p < threshold_squared: # 这里继续执行后续的素性测试(比如Miller-Rabin) # 示例:假设is_prime是你实现的素性检测函数 # if is_prime(p): # return p print(f"Passed threshold check: {p}") break generate_random_prime()
额外说明
- 不用担心
p*p的性能问题:Python对大整数的乘法优化得很好,1024位整数的乘法完全在可接受的范围内 - 这个变形完全符合FIPS186-4的数学要求,没有偏离标准
内容的提问来源于stack exchange,提问作者GenXGer
相关产品推荐
相关产品推荐

