【问题标题】:Sieve Of Atkin Implementation in Python在 Python 中实现 Atkin 筛选
【发布时间】:2014-03-14 00:55:24
【问题描述】:

我正在尝试实现维基百科链接中给出的阿特金筛算法如下:

Sieve Of Atkin

到目前为止,我尝试的是以下代码给出的 Python 实现:

import math
is_prime = list()
limit = 100
for i in range(5,limit):
    is_prime.append(False)

for x in range(1,int(math.sqrt(limit))+1):
    for y in range(1,int(math.sqrt(limit))+1):
        n = 4*x**2 + y**2

        if n<=limit and (n%12==1 or n%12==5):
            # print "1st if"
            is_prime[n] = not is_prime[n]
        n = 3*x**2+y**2
        if n<= limit and n%12==7:
            # print "Second if"
            is_prime[n] = not is_prime[n]
        n = 3*x**2 - y**2
        if x>y and n<=limit and n%12==11:
            # print "third if"
            is_prime[n] = not is_prime[n]

for n in range(5,int(math.sqrt(limit))):
    if is_prime[n]:
        for k in range(n**2,limit+1,n**2):
            is_prime[k] = False
print 2,3
for n in range(5,limit):
    if is_prime[n]: print n

现在我得到错误

is_prime[n] = not is_prime[n]
IndexError: list index out of range

这意味着我正在访问列表中索引大于列表长度的值。考虑 x,y = 100 时的条件,那么当然条件 n=4x^2+y^2 将给出大于列表长度的值。我在这里做错了吗?请帮忙。

编辑 1 正如 Gabe 所建议的,使用

is_prime = [False] * (limit + 1)

安装:

for i in range(5,limit):
    is_prime.append(False)

确实解决了问题。

【问题讨论】:

  • 按照 gabe 的建议添加该行时,代码运行良好。

标签: python


【解决方案1】:

你的问题是你的限制是 100,但你的 is_prime 列表中只有 limit-5 元素,因为它是用 range(5, limit) 初始化的。

由于此代码假定它最多可以访问limit 索引,因此您需要在其中包含limit+1 元素:is_prime = [False] * (limit + 1)

请注意,4x^2+y^2 是否大于 limit 并不重要,因为它始终检查 n &lt;= limit

【讨论】:

  • 我在附加到 is_prime 时添加了 range(5, limit+1) 但收到错误。
  • range(x, y) 返回 y-x 元素,因此您的 is_prime 列表的索引范围为 0 到 95。您需要它的索引范围为 0 到 101。使用 is_prime = [0] * (limit + 1) 创建列表.
  • Gabe 你能不能参考维基百科中给出的链接。它给出了 1 到 95 的范围,包括两者
  • 他们用False 初始化他们的列表,而不是0,所以它可能应该是[False] * (limit + 1)。 (并不是说它对实现有影响,但它应该使它更类似于原来的)
  • @SarvagyaPant:你知道在 Python 中列表总是从索引 0 开始吗​​?无论您在range() 调用中输入什么数字,第一次调用is_prime.append() 时,您都会创建索引0。第95 次调用is_prime.append() 时,无论事实上i 是 100!
【解决方案2】:

这里有一个解决方案

import math

def sieveOfAtkin(limit):
    P = [2,3]
    sieve=[False]*(limit+1)
    for x in range(1,int(math.sqrt(limit))+1):
        for y in range(1,int(math.sqrt(limit))+1):
            n = 4*x**2 + y**2
            if n<=limit and (n%12==1 or n%12==5) : sieve[n] = not sieve[n]
            n = 3*x**2+y**2
            if n<= limit and n%12==7 : sieve[n] = not sieve[n]
            n = 3*x**2 - y**2
            if x>y and n<=limit and n%12==11 : sieve[n] = not sieve[n]
    for x in range(5,int(math.sqrt(limit))):
        if sieve[x]:
            for y in range(x**2,limit+1,x**2):
                sieve[y] = False
    for p in range(5,limit):
        if sieve[p] : P.append(p)
    return P

print sieveOfAtkin(100)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-06
    • 1970-01-01
    相关资源
    最近更新 更多