Java 理解Eratosthenes算法筛的一个改进变体

Java 理解Eratosthenes算法筛的一个改进变体,java,algorithm,primes,Java,Algorithm,Primes,我在一个编码站点(没有作者的信息)上遇到了这个算法,它计算的所有素数都小于给定的限制。它看起来与SoE算法非常相似,但在计算素数的方式上有所不同: public int countPrimes(int n) { if (n < 3) return 0; boolean[] s = new boolean[n]; int c = n / 2; for (int i = 3; i < Math.sqrt(n); i += 2) { if (

我在一个编码站点(没有作者的信息)上遇到了这个算法,它计算的所有素数都小于给定的限制。它看起来与SoE算法非常相似,但在计算素数的方式上有所不同:

public int countPrimes(int n) {
    if (n < 3) return 0;
    boolean[] s = new boolean[n];
    int c = n / 2;
    for (int i = 3; i < Math.sqrt(n); i += 2) {
        if (s[i]) continue;
        for (int j = i * i; j < n; j += 2 * i) {
            if (!s[j]) {
                c--;
                s[j] = true;
            }
        }
    }
    return c;
}
public int countPrimes(int n){
如果(n<3)返回0;
布尔值[]s=新的布尔值[n];
int c=n/2;
对于(int i=3;i

它将初始计数设置为限制的一半,然后将其递减,但我似乎无法理解为什么这样做有效。有人能解释一下吗?

计数被初始化为n/2,因为所有偶数(2除外)都不是素数。 然后下面的循环可以从3的倍数开始检查。
如果发现一个新的非素数(!s[j]),则素数(c)的计数将减少。

首先,布尔数组s表示SoE

第一个循环将奇数从3迭代到sqrt(n)(因为除2之外的所有偶数都不是素数)。 在第6行,如果i已经在s中,则继续下一个奇数。如果不是,将小于或等于ni的所有倍数添加到第二个循环中的s


此外,第二个循环从i*i开始,因为i小于i*i的所有倍数都已经在前面的循环中检查过了。

只有奇数才是素数的可行候选数,其中有
n/2
个。解释是一个大而广泛的问题,也许可以帮助你更多,这家伙在解释素数+复合数==范围内所有数的个数方面做得相当好。考虑到
n/2
被打倒,n是偶数还是奇数不重要吗?其次,
n/2
是小于n的奇数的计数,那么它不意味着素数2被排除在计数之外吗?1。n/2会自动被加上下限(因为c是整数)//2。否,楼层(n/2)指小于n的奇数。但1不是素数,因此我们可以将1替换为2。