【问题标题】:How to optimize Sieve of Eratosthenes further如何进一步优化 Eratosthenes 筛
【发布时间】:2018-05-29 03:05:31
【问题描述】:

我正在解决 Project Euler 问题 10,并且我能够使用 Eratosthenes 筛解决此问题,但现在我想进一步优化代码。

考虑到所有大于 3 的素数都是 6k+16k-1 的形式,我只将数组中的这些值设置为 true,但并非所有这种形式的数字都是素数,所以我必须筛选值并删除非素数,我的代码如下:

public static bool[] GeneratePrimes(int bound)
    {
        bool[] isPrime = new bool[bound];
        isPrime[2] = true;
        isPrime[3] = true;

        // Taking into account that all primes greater than 2 and 3
        // Are of the form 6k+1 or 6k-1

        for (int k = 6; k < isPrime.Length; k += 6)
        {
            if (k + 1 < isPrime.Length) isPrime[k + 1] = true;
            isPrime[k - 1] = true;
        }

        // At this point we still have some numbers that aren't prime marked as prime
        // So we go over them with a sieve, also we can start at 3 for obvious reasons

        for (int i = 3; i * i <= bound; i += 2)
        {
            if (isPrime[i])
            {
                // Can this be optimized?
                for (int j = i; j * i <= bound; j++)
                    isPrime[i * j] = false;
            }
        }

        return isPrime;
    }
}

那么,如何优化通过较少数字筛选出来的代码呢?例如,如果我的数字是 5,那么 10、15、20 之类的数字已经被划过,但例如 25 不是这样,是否可以只通过 25 等值?

【问题讨论】:

  • 将您范围内的所有数字列在一个列表中。将它们从您的列表中删除是您浏览它们的原因。
  • 你可以推广到更大的primtorials,例如所有 > 5 的素数的形式为 30k+{1, 7, 11, 13, 17, 19, 23, 29},所有 > 7 的素数的形式为 210k + {1, 11, 13, 17, 19, 23, 29、31、37、41、43、47、53、59、61、67、71、73、79、83、89、97、101、103、107、109、113、121、127、131、137、 139、143、149、151、157、163、167、169、173、179、181、187、191、193、197、199、209}。以此类推。

标签: c# optimization primes sieve-of-eratosthenes


【解决方案1】:

Paul Pritchard 在轮式筛子方面做了很多工作,将您的 6k±1 想法扩展到更大的主要*。谷歌搜索“pritchard 轮筛”或查看my blog 以开始使用。

【讨论】:

    【解决方案2】:

    消除素数p的倍数时,只需从p * p开始。任何低于 p 的倍数都将被消除,因为它具有较小的素因数。这就是你的 cmets 大约 5 和 25 背后的原因。

    【讨论】: