Python:需要高int精度的解决方案(生成素数)

时间:2018-05-04 18:34:29

标签: python math int decimal primes

目前我尝试使用NIST的FIPS186-4(附录B3.2.1)中显示的算法实现generate_random_prime() - 函数,请参阅here

但是步骤4.4似乎有一个大问题(如果p< sqrt(2)*(2 **((nlen / 2)-1)),因为Python的精确性。

显示我的代码的相关部分和问题,请参阅此示例:

import os
from decimal import Decimal
import math

for i in range(100):
    nlen = 2048 #my key-size should be 2048bit
    p = int.from_bytes(os.urandom(int(2048/2/8)), byteorder = "little") #see Ann1 and Ann2

    print(p < Decimal(math.sqrt(2))*(Decimal(2**(int(2048/2))) - 1)

Ann1:2048/2/8因为字节 Ann2:我知道os.urandom不是最好的发电机 - 我后来会使用一个批准的发电机......在测试阶段我认为应该是可以接受的......

结果总是&#34; True&#34; - 所以算法永远不会离开步骤4.4。

我认为问题是Decimal(math.sqrt(2))*(Decimal(2**(int(2048/2))) - 1),因为结果是Decimal('2.542322012307292741109308792E+308')。通过int(Decimal(math.sqrt(2))*(Decimal(2**(int(2048/2))) - 1))转换为int,结果将是

254232201230729274110930879200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

它被围捕了! - 这是永远真实结果的原因吗?我认为在这种情况下,永远不可能得到小于Decimal(math.sqrt(2))*(Decimal(2**(int(2048/2))) - 1)

的p

我该如何解决这个问题?

__ 编辑:发现一个错误: Decimal(math.sqrt(2))*(Decimal(2**(int(2048/2))) - 1)应为Decimal(math.sqrt(2))*(Decimal(2**(int(2048/2-1)))),因此结果应为Decimal('1.271161006153646370554654396E+308')而不是Decimal('2.542322012307292741109308791E+308')

1 个答案:

答案 0 :(得分:2)

您不断在浮点数,整数和Decimal之间进行转换。放弃使用float;这包括不使用生成float值的函数,例如math.sqrt()

改为坚持Decimal个对象,只将最终值转换为整数:

int(Decimal(2).sqrt() * 2 ** ((nlen // 2) - 1))

注意//的使用,使用整数除法,而不是真正的除法(再次产生浮动)。