【发布时间】:2013-01-30 20:39:34
【问题描述】:
今天一直在尝试实现 Rabin-Miller 强伪素检验。
已使用Wolfram Mathworld 作为参考,第 3-5 行很好地总结了我的代码。
但是,当我运行程序时,它(有时)会说素数(甚至低,例如 5、7、11)不是素数。看了很长时间的代码,没搞清楚哪里出了问题。
为了寻求帮助,我查看了这个站点以及许多其他站点,但大多数都使用了另一个定义(可能相同,但由于我是这种数学的新手,我看不出同样的明显联系)。
我的代码:
import random
def RabinMiller(n, k):
# obviously not prime
if n < 2 or n % 2 == 0:
return False
# special case
if n == 2:
return True
s = 0
r = n - 1
# factor n - 1 as 2^(r)*s
while r % 2 == 0:
s = s + 1
r = r // 2 # floor
# k = accuracy
for i in range(k):
a = random.randrange(1, n)
# a^(s) mod n = 1?
if pow(a, s, n) == 1:
return True
# a^(2^(j) * s) mod n = -1 mod n?
for j in range(r):
if pow(a, 2**j*s, n) == -1 % n:
return True
return False
print(RabinMiller(7, 5))
这与 Mathworld 给出的定义有何不同?
【问题讨论】:
-
为什么会有Java作为标签?在我看来像 Python...
-
如果您使用 Java,也许您可以向我们展示您的 Java 代码以与算法进行比较。
-
对不起,最初是用 Java 写的,后来用 Python 重写,以便于阅读。然后,当我发布时,我不允许创建新标签(不是说 Python 是新标签),而是选择了 Java,因为我全都参与其中。再次抱歉。
-
你应该把
if n == 2放在检查偶数之前,否则你会在检查数字是否为2之前返回False。 -
FWIW 很多逻辑都在这里翻转。 Rabin-Miller 背后的想法是你测试一堆东西,如果数字是素数,它们就会通过,所以如果它们不通过,那么它就是复合的。现在,只要任何测试恰好通过,您就会返回 True。相反,你真的想测试这些条件,如果它们失败,那么你应该返回 False,最后返回 True(意味着可能是素数)。