2

我编写了一个简单的 python 模块,该模块返回给定 N 的素数,使用 bool 标志is_prime,如下所示:

def generate_primes_up_to(M):
    n = 2
    primes = []    
    while n <= M:
        is_prime = True
        for p in primes:
            if p**2 > n: break
            if n % p == 0:
                is_prime = False
                break
        if is_prime: primes.append(n) 
        n += 1
    return primes

if __name__ == '__main__':
    generate_primes_up_to(100)

输出:

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

现在,这实际上是使用for-else构造的理想情况,因为n只有在循环中没有break出现 s 时,数字才是素数。for因此,我将函数更改为:

def generate_primes_up_to(M, flag='nonumpy'):
    n = 2
    primes = []    
    while n <= M:
        for p in primes:
            if p**2 > n: break
            if n % p == 0: break
        else: primes.append(n) 
        n += 1
    return primes

但现在代码输出:

[2, 5, 27]

我不明白为什么该if p**2 > n: break表达式会干扰for-else子句的流程。如果我删除该行,代码将再次产生正确的输出。

4

2 回答 2

4

导致问题的条件是 -

if p**2 > n: break

举个例子 - 7,当我们检查 7 是否是素数时,我们已经发现 -是素数,当我们检查as =大于时[2,3,5],上述条件会中断for循环。33**297

删除该条件,它工作正常(虽然它很慢)。

在原始循环中(没有 for-else 构造),它起作用了,因为在那种情况下,您刚刚跳出循环,您没有更改标志is_prime


使用该for..else构造,发生的情况是,该部分仅在我们退出循环而不使用语句else时才执行。break

但是在上述条件的情况下,我们使用break语句,因此else部分不执行。

于 2015-08-02T08:47:25.443 回答
1

您还可以使用next

def generate_primes_up_to(M):
    n = 2
    primes = []
    while n <= M:
        if next((False for p in primes if not n % p), True):
            primes.append(n)
        n += 1

    return primes
于 2015-08-02T10:56:24.113 回答