【问题标题】:Why is my implementation of the Sieve of Atkin overlooking numbers close to the specified limit?为什么我实施的阿特金筛法忽略了接近指定限制的数字?
【发布时间】:2010-03-08 02:00:54
【问题描述】:

我对@9​​87654321@ 的实现要么忽略接近极限的素数,要么忽略接近极限的复合。有些限制有效,有些则无效。我完全不知道出了什么问题。

def AtkinSieve (limit):
results = [2,3,5]
sieve = [False]*limit
factor = int(math.sqrt(lim))
for i in range(1,factor):
    for j in range(1, factor):
        n = 4*i**2+j**2
        if (n <= lim) and (n % 12 == 1 or n % 12 == 5):
            sieve[n] = not sieve[n]
        n = 3*i**2+j**2
        if (n <= lim) and (n % 12 == 7):
            sieve[n] = not sieve[n]
        if i>j:
            n = 3*i**2-j**2
            if (n <= lim) and (n % 12 == 11):
                sieve[n] = not sieve[n]
for index in range(5,factor):
    if sieve[index]:
        for jndex in range(index**2, limit, index**2):
            sieve[jndex] = False
for index in range(7,limit):
    if sieve[index]:
        results.append(index)
return results

例如,当我生成一个限制为 1000 的素数时,阿特金筛漏掉了素数 997,但包含了复合 965。但如果我生成限制为 5000,它返回的列表是完全正确的。

【问题讨论】:

    标签: python math primes sieve-of-atkin


    【解决方案1】:

    • lim 更改为 limit。当然,你一定知道这一点。
    • 由于sieve = [False]*limit, 允许的最大索引是limit-1

      但是,在这一行

      if (n <= limit) and (n % 12 == 1 or n % 12 == 5):
      

      你正在检查n&lt;=limit。如果n==limitsieve[n] 引发IndexError。 使用较小的 limit 值尝试您的算法(例如 n=50)。你会看到这个错误出现。 一个简单的解决方法是使用

      sieve = [False]*(limit+1)
      

      简单的修复有点浪费,因为 sieve[0] 从未使用过。因此,您可能认为更好的解决方法是保留sieve = [False]*limit,但通过将sieve 上的索引减一来修复所有其他代码。 (例如,在任何地方将 sieve[n] 更改为 sieve[n-1] 等)但是,这将迫使您进行一些额外的减法,这对速度不利。因此,简单/浪费的解决方案实际上可能是更好的选择。

    • 根据http://en.wikipedia.org/wiki/Sieve_of_Atkin, x 应该是 [1,sqrt(limit)] 中的整数,包括端点。

      在您的代码中

      factor = int(math.sqrt(limit))
      

      int 占据math.sqrt(limit)楼层。此外,

      range(1,factor) 从 1 变为因子-1。所以你早了 1 点。

      所以你需要把它改成

      factor = int(math.sqrt(limit))+1
      

    • 请参阅 Fastest way to list all primes below N 了解阿特金筛的替代(和更快)实现,由 Steve Krenzel 提供。
    def AtkinSieve (limit):
        results = [2,3,5]
        sieve = [False]*(limit+1)
        factor = int(math.sqrt(limit))+1
        for i in range(1,factor):
            for j in range(1, factor):
                n = 4*i**2+j**2
                if (n <= limit) and (n % 12 == 1 or n % 12 == 5):
                    sieve[n] = not sieve[n]
                n = 3*i**2+j**2
                if (n <= limit) and (n % 12 == 7):
                    sieve[n] = not sieve[n]
                if i>j:
                    n = 3*i**2-j**2
                    if (n <= limit) and (n % 12 == 11):
                        sieve[n] = not sieve[n]
        for index in range(5,factor):
            if sieve[index]:
                for jndex in range(index**2, limit, index**2):
                    sieve[jndex] = False
        for index in range(7,limit):
            if sieve[index]:
                results.append(index)
        return results
    

    【讨论】:

    • 是的,在用 Java 编程之后,我注意到了所有这些错误......不过,我一定会检查一下更快的实现。
    猜你喜欢
    • 1970-01-01
    • 2010-11-04
    • 1970-01-01
    • 2020-03-11
    • 1970-01-01
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多