【问题标题】:Class that checks for primes not working properly检查素数的类不能正常工作
【发布时间】:2026-01-29 02:45:02
【问题描述】:

我为与素数相关的所有内容创建了一个名为 Primes 的类。它包含一个名为 isPrime 的方法,该方法使用另一个名为 sieveOfAtkin 的方法,该方法创建一个名为 sieve 的布尔数组,其索引值从 0 到 1000000。用户将整数 n 传递给 isPrime 方法。如果 sieve[n]=true,那么整数 n 是素数。否则 isPrime 返回 false。我的问题是,当我使用我知道是素数的数字测试此方法时,它总是返回 false。以这行代码为例,测试 13 是否为质数:

public class Test {
 public static void main(String[] args) {
  Primes pr=new Primes(); // Creates Primes object
  System.out.println(pr.isPrime(13)); 
 }
}

即使我们知道 13 是质数,输出也是错误的。这是我的整个 Primes 类的代码https://github.com/javtastic/project_euler/blob/master/Primes.java

它使用阿特金筛,这被认为是测试素数的最有效方法。更多信息可以在这里找到:http://en.wikipedia.org/wiki/Sieve_of_Atkin

我不完全确定我做错了什么。我已经尝试了几个小时来找出导致此错误的原因,但我仍然得到相同的结果(一切都是错误的)。也许我应该找到另一种检查素数的方法?

【问题讨论】:

  • 代码有效,我已粘贴输出
  • 如果你使用像 Atkin 这样复杂的算法,而像 Erothosthenes 这样更简单的算法就能完成工作,那是在浪费你的时间。

标签: java


【解决方案1】:

使用这个:

public static boolean isPrime(int number) {
    int sqrt = (int) Math.sqrt(number) + 1;
    for (int i = 2; i < sqrt; i++) {
        if (number % i == 0) {
            return false;
        }
    }
    return true;
}

【讨论】:

  • 这是一个 Eratosthenes 筛子,如果您要测试大量数字,效率会稍低。
【解决方案2】:

代码对我来说就像一个魅力,没有做任何更改。

代码

import java.util.Arrays;

public class Test {
    // This class uses a Atkin sieve to determine all prime numbers less than int limit
    // See http://en.wikipedia.org/wiki/Sieve_of_Atkin
    private static final int       limit     = 1000000;
    private final static boolean[] sieve     = new boolean[limit + 1];
    private static int             limitSqrt = (int) Math.sqrt(limit);

    public static void sieveOfAtkin() {
        // there may be more efficient data structure
        // arrangements than this (there are!) but
        // this is the algorithm in Wikipedia
        // initialize results array
        Arrays.fill(sieve, false);
        // the sieve works only for integers > 3, so
        // set these trivially to their proper values
        sieve[0] = false;
        sieve[1] = false;
        sieve[2] = true;
        sieve[3] = true;
        // loop through all possible integer values for x and y
        // up to the square root of the max prime for the sieve
        // we don't need any larger values for x or y since the
        // max value for x or y will be the square root of n
        // in the quadratics
        // the theorem showed that the quadratics will produce all
        // primes that also satisfy their wheel factorizations, so
        // we can produce the value of n from the quadratic first
        // and then filter n through the wheel quadratic
        // there may be more efficient ways to do this, but this
        // is the design in the Wikipedia article
        // loop through all integers for x and y for calculating
        // the quadratics
        for (int x = 1 ; x <= limitSqrt ; x++) {
            for (int y = 1 ; y <= limitSqrt ; y++) {
                // first quadratic using m = 12 and r in R1 = {r : 1, 5}
                int n = (4 * x * x) + (y * y);
                if (n <= limit && (n % 12 == 1 || n % 12 == 5)) {
                    sieve[n] = !sieve[n];
                }
                // second quadratic using m = 12 and r in R2 = {r : 7}
                n = (3 * x * x) + (y * y);
                if (n <= limit && (n % 12 == 7)) {
                    sieve[n] = !sieve[n];
                }
                // third quadratic using m = 12 and r in R3 = {r : 11}
                n = (3 * x * x) - (y * y);
                if (x > y && n <= limit && (n % 12 == 11)) {
                    sieve[n] = !sieve[n];
                }
                // note that R1 union R2 union R3 is the set R
                // R = {r : 1, 5, 7, 11}
                // which is all values 0 < r < 12 where r is
                // a relative prime of 12
                // Thus all primes become candidates
            }
        }
        // remove all perfect squares since the quadratic
        // wheel factorization filter removes only some of them
        for (int n = 5 ; n <= limitSqrt ; n++) {
            if (sieve[n]) {
                int x = n * n;
                for (int i = x ; i <= limit ; i += x) {
                    sieve[i] = false;
                }
            }
        }
    }

    // isPrime method checks to see if a number is prime using sieveOfAtkin above
    // Works since sieve[0] represents the integer 0, sieve[1]=1, etc
    public static boolean isPrime(int n) {
        sieveOfAtkin();
        return sieve[n];
    }

    public static void main(String[] args) {
        System.out.println(isPrime(13));
    }
}

Input - 13, Output - True
Input -23, Output - True
Input - 33. output - False

【讨论】:

  • 我正在查看您所做的更改,看起来我忘记声明 sieveOfAtkin();在我的 isPrime 方法中。我还将所有公共变量和方法设为静态。但是,对于为什么这解决了问题,我仍然有些困惑。是什么让公共静态变量与公共变量不同?
  • @slayer static 没有任何区别,你忘了调用sieveOfAtkin(); 方法,所以默认你得到false
  • 我不敢相信我没听懂,不过感谢您的帮助。