如何解决为什么大整数的经典除法“/”比整数除法“//”慢得多?
我遇到了一个问题:如果您对 (p-1)/2 使用经典除法,那么对于 512 位奇数,代码会非常慢。但是通过楼层划分,它可以立即生效。是浮点转换引起的吗?
def solovayStrassen(p,iterations):
for i in range(iterations):
a = random.randint(2,p - 1)
if gcd(a,p) > 1:
return False
first = pow(a,int((p - 1) / 2),p)
j = (Jacobian(a,p) + p) % p
if first != j:
return False
return True
完整代码
import random
from math import gcd
#Jacobian symbol
def Jacobian(a,n):
if (a == 0):
return 0
ans = 1
if (a < 0):
a = -a
if (n % 4 == 3):
ans = -ans
if (a == 1):
return ans
while (a):
if (a < 0):
a = -a
if (n % 4 == 3):
ans = -ans
while (a % 2 == 0):
a = a // 2
if (n % 8 == 3 or n % 8 == 5):
ans = -ans
a,n = n,a
if (a % 4 == 3 and n % 4 == 3):
ans = -ans
a = a % n
if (a > n // 2):
a = a - n
if (n == 1):
return ans
return 0
def solovayStrassen(p,p) + p) % p
if first != j:
return False
return True
def findFirstPrime(n,k):
while True:
if solovayStrassen(n,k):
return n
n+=2
a = random.getrandbits(512)
if a%2==0:
a+=1
print(findFirstPrime(a,100))
解决方法
如注释中所述,如果 int((p - 1) / 2)
是一个超过 53 位的整数,则 p
会产生垃圾。为除法转换为浮点数时,仅保留 p-1
的前 53 位。
>>> p = 123456789123456789123456789
>>> (p-1) // 2
61728394561728394561728394
>>> hex(_)
'0x330f7ef971d8cfbe022f8a'
>>> int((p-1) / 2)
61728394561728395668881408
>>> hex(_) # lots of trailing zeroes
'0x330f7ef971d8d000000000'
当然,素性测试的基础理论依赖于完全使用(p-1)/2
的无限精确值,而不是某些近似值或多或少仅适用于前 53 个最重要的值位。
正如评论中所指出的,使用垃圾很可能会使这部分返回得更早,而不是更晚:
if first != j:
return False
那么为什么它总体上要慢得多?因为 findFirstPrime()
必须多次调用 solovayStrassen()
才能找到纯粹靠运气的垃圾。
要看到这一点,请更改代码以显示循环尝试的频率:
def findFirstPrime(n,k):
count = 0
while True:
count += 1
if count % 1000 == 0:
print(f"at count {count:,}")
if solovayStrassen(n,k):
return n,count
n+=2
然后添加,例如
random.seed(12)
在主程序开始时,这样您就可以获得可重现的结果。
使用楼层(//
)除法,运行速度相当快,显示
(6170518232878265099306454685234429219657996228748920426206889067017854517343512513954857500421232718472897893847571955479036221948870073830638539006377457,906)
所以它在第 906 次尝试中找到了一个可能的素数。
但是使用浮动 (/
) 除法,我从未见过它靠运气成功:
at count 1,000
at count 2,000
at count 3,000
...
at count 1,000,000
然后放弃 - “垃圾进,垃圾出”。
还有一点要注意,顺便说一下:+ p
in:
j = (Jacobian(a,p) + p) % p
对 j
的值没有影响。对? p % p
为 0。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。