我有一个Miller-Rabin素数测试器的伪代码:
function isPrime(n, k=5)
if n < 2 then return False
for p in [2,3,5,7,11,13,17,19,23,29]
if n % p == 0 then return n == p
s, d = 0, n-1
while d % 2 == 0
s, d = s+1, d/2
for i from 0 to k
x = powerMod(randint(2, n-1), d, n)
if x == 1 or x == n-1 then next i
for r from 1 to s
x = (x * x) % n
if x == 1 then return False
if x == n-1 then next i
return False
return True
但由于内部next i
循环中的for
语句必须断开两个循环,因此将其转换为Python很难。 Python中没有goto
。在Stack Overflow上提出这个问题的其他提问者被告知要使用return
或try/except
条件或其他布尔标志的本地函数,但这些解决方案要么不要在这里申请或者会大大改变这个可爱的伪代码。
这个问题的Pythonic方法是什么?
答案 0 :(得分:3)
我认为pythonic方法是try / except,可读性更喜欢方法或布尔值,但我认为这可以通过添加一行来解决:
for i in xrange(k):
x = powerMod(randint(2, n-1), d, n)
if x == 1 or x == n-1: continue
for r in xrange(1,s):
x = (x * x) % n
if x == 1: return False
if x == n-1: break #*
if x != n-1: #added line
return False
return True
打破标有#*的行是有问题的,因为它返回false,但如果我们修复它就像“下一个”。
tobias_k建议的另一个解决方案是使用/ else:
for i in xrange(k):
x = powerMod(randint(2, n-1), d, n)
if x == 1 or x == n-1: continue
for r in xrange(1,s):
x = (x * x) % n
if x == 1: return False
if x == n-1: break
else: #added line
return False
return True
如果循环为return False
,则不会调用 break
语句 - 仅当它已用完时才会被调用。
答案 1 :(得分:1)
您可以将break
和continue
与for: else
一起使用。
for i from 0 to k
x = powerMod(randint(2, n-1), d, n)
# Use 'continue' to go to next i (skip inner loop).
if x == 1 or x == n-1 then next i
for r from 1 to s
x = (x * x) % n
if x == 1 then return False
# Use 'break' to exit this loop and go to next i
# since this loop is at the end of the i loop.
if x == n-1 then next i
else:
# This is only reached if no `break` occurred
return False
return True
答案 2 :(得分:0)
Try
和except
在这里可以很好地工作。
class BreakException(Exception):
pass
try:
for a in range(4532):
for b in range(4328):
for c in range(47328):
for d in range(5993):
if something:
raise BreakException
except BreakException:
pass