【问题标题】:Sieve of Eratosthenes will not sieve Prime Numbers埃拉托色尼筛法不会筛选素数
【发布时间】:2017-11-14 12:48:30
【问题描述】:

对于我正在为我的一个班级做的一项作业,我们必须实施埃拉托色尼筛法。我已经尝试了七次以获得有效的代码,并尝试整合我研究过的众多解决方案。我终于有一个可以输出数字的了。不幸的是,它同时打印复合数和素数,并且不打印 2。

我的代码如下:

public class EratosthenesSieveAttempt6 {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        Scanner keyboard = new Scanner(System.in);
        int limit;

        System.out.print("Please enter the highest number to check "
                + "(number must be greater than 2): ");

        limit = keyboard.nextInt();

        while (limit <= 2){
          System.out.println("Error - number must be greater than 2.");
          System.out.println("Please enter the highest number to check: ");
          limit = keyboard.nextInt();
        }

        boolean[] numbers = new boolean[limit + 1];
        int newPrime = 2;

        for(int i = 0; i < limit + 1; i++){
          numbers[i] = true;       
        }

        for(int j = 1; j < limit + 1; j++) {
          if (j % 2 == 0) {
           numbers[j] = false;   
           }

        for(int k = j + 1; k < limit + 1; k++) {
           if(numbers[k] == true){
             j = k;

        System.out.println(k);
               }
            }
         }
       }
    }

我怀疑我的循环有问题。我为前两个循环修复了ij 变量,以便它从2 开始打印出来,问题似乎是在我将数组初始化为@987654324 后它没有将复合数标记为假@。

提前感谢您的帮助。

【问题讨论】:

  • 这不是 eratosthenes 方法并且不起作用,您必须在列表中进行变量乘法 false
  • @Mohsen_Fatemi 哪些变量?我必须从它们都被标记为假开始吗?我需要完全重写代码吗?
  • 请修正缩进以使代码可读!!
  • 您的代码检查数字是否可以除以 2。这还不够,您应该检查 3、(4)、5、​​(6)、7 等。所以您需要嵌套循环。可以检查括号中的数字,但这不是必需的(您可以在数组中认识到这一点:如果某些东西已经为假,则不需要进一步检查,它的乘法已经处理)。此外,当您检查数字是否可被 n 整除时,您应该从 n+1 开始检查(例如,3 可以被 3 整除,但它是质数,而 6、9、12 等则不能)。事实上,真正的筛子不会分裂,它会倍增。
  • 看你知道2 是素数,那么它的乘法不是素数` 4 , 6 , 8 , 10 , 12 , 14 , ...必须转到下一个数字3 是素数所以` 6 , 9 , 12 , 15 , ...` 不是素数并且必须被标记,那么下一个数字将是5 等等,你必须这样做这与 ij 变量

标签: java for-loop sieve-of-eratosthenes


【解决方案1】:

这是我前几天写的埃拉托色尼筛法的一个实现:

import java.util.BitSet;

public static BitSet composite(int max) {
    BitSet composite = new BitSet(max);
    max = composite.size();
    for (int i = 4; i < max; i += 2) composite.set(i, true);
    for (int i = 9; i < max; i += 6) composite.set(i, true);
    int p = 5;
    while (p*p < max) {
        if (!composite.get(p)) {
            for (int i = p*p; i < max; i += p*2) composite.set(i, true);
        }
        p += 2;
        if (p*p >= max) break;
        if (!composite.get(p)) {
            for (int i = p*p; i < max; i += p*2) composite.set(i, true);
        }
        p += 4;
    }
    return composite;
}

注意事项:

  • BitSet分配64位字,所以大小可能比你要求的大(比如你要求它上去1000,它就会上去1024;这就是max = composite.size()靠近顶部的原因)
  • 明确排除 2、3,然后
  • 依赖于所有大于 3 的素数都与 1 或 5 mod 6 一致的事实;这就是最终循环在加 2 和 4 之间交替的原因

它返回一个BitSet,告诉您哪些数字是合数。从中提取素数的一种方法是:

public static int[] primes(BitSet composite) {
    int size = composite.size() - 2 - composite.cardinality();
    int[] primes = new int[size];
    int index = 0;
    for (int i = 2; i < composite.size(); i++) {
        if (!composite.get(i)) primes[index++] = i;
    }
    return primes;
}

【讨论】:

  • 我不知道 BitSet 是 Java 中的一个类!知道这一点很有帮助。我可以遵循其中的一些; .size().cardinality() 都是该类的方法吗?
  • @KMN 是的。请参阅BitSet documentation 了解更多信息。
猜你喜欢
  • 1970-01-01
  • 2013-10-21
  • 1970-01-01
  • 2011-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多