我的主要测试代码有什么问题?

时间:2011-06-26 02:06:43

标签: python algorithm primes

我使用Python 3实现了维基百科上的Miller-Rabin prime test algorithm

它似乎与大多数数字一起正常工作,但偶尔会因某些数字而失败。

例如,素数99999999999999997被判定为非素数。

我逐行实现了算法,我不知道问题出在哪里。 任何人都可以帮助我吗?

这是我的代码。

测试输入是:

1

99999999999999997

(两行之间没有空行。)

预期的输出应该是YES,但它在我的机器上没有。

import random

def isPrime(n, k = 5):
'''
Primality test using Miller-Rabin method.
n The number to test primality.
k The number of M-R test to perform.
'''
if n == 1:
    return False
if n == 2 or n == 3:
    return True
if n % 2 == 0:
    return False

# Calculate d
nn = n - 1
s = 1
while nn % (2 ** s) == 0:
    s += 1
s -= 1
d = int(nn / (2 ** s))

for i in range(k):
    a = random.randint(2, n - 1)
    x = pow(a,d,n)
    if x == 1 or x == n - 1:
        continue
    flag = True
    for r in range(1, s):
        x = pow(x,2,n)
        if x == 1:
            return False
        if x == n - 1:
            flag = False
            break
    if not flag:
        continue
    return False
return True

count = int(input())
for i in range(count):
    if isPrime(int(input())):
        print('YES')
    else:
        print('NO')

3 个答案:

答案 0 :(得分:4)

这是我前一段时间写过的Miller-Rabin的实现。它从来没有给我一个意想不到的结果 - 虽然这并不意味着它不会!它与您粘贴的基本相同,并声明99999999999999997是素数。当我测试它时,你也做了 - 所以这是Mikola's opinion的第二个。 但请参阅下面的一个我无法轻易测试的可能问题...从头开始,我测试了它,这就是问题

说到素性测试,我不是专家,但我花了很多时间思考并了解Miller-Rabin,我很确定你的实现是正确的。

def is_prime_candidate(self, p, iterations=7):  
    if p == 1 or p % 2 == 0: return False       
    elif p < 1: raise ValueError("is_prime_candidate: n must be a positive integer")
    elif p < self.maxsmallprime: return p in self.smallprimes

    odd = p - 1
    count = 0
    while odd % 2 == 0:
        odd //= 2
        count += 1

    for i in range(iterations):
        r = random.randrange(2, p - 2) 
        test = pow(r, odd, p)
        if test == 1 or test == p - 1: continue
        for j in range(count - 1):
            test = pow(test, 2, p)
            if test == 1: return False
            if test == p - 1: break
        else: return False
        print i
    return True

我注意到你的代码似乎关闭的一件事是:

d = int(nn / (2 ** s))

为什么int,我心想。然后我意识到你必须使用Python 3.这意味着你在这里做浮点算术然后转换为int。这似乎不合时宜。所以我在ideone上测试了它。 And lo!结果为False。所以我将代码更改为使用显式楼层划分(d = nn // (2 ** s))。 And lo!它是True

答案 1 :(得分:2)

我将重申我的评论,因为我的测试似乎表明你的例子正在发挥作用。我强烈怀疑你错误地输入了测试用例。也许你可以尝试再看看它?这是我从运行它得到的:

  

在[12]中:millerrabin.isPrime(99999999999999997,5)

     

Out [12]:True

编辑:我刚刚运行了更新版本,这是控制台的输出:

1
99999999999999997
YES

再次,这看起来是正确的。

答案 2 :(得分:0)

从我所看到的,Miller-Rabin算法只是概率性的。您是否意识到这一点,或者您使用的是经过修改的非概率版本?