简体   繁体   English

Eratosthenes筛网-实现返回一些非素值?

[英]Sieve of Eratosthenes - Implementation returning some non-prime values?

I implemented the Sieve of Eratosthenes in Java, from pseudocode: 我用伪代码在Java中实现了Eratosthenes筛子:

public static void sieveofEratosthenes(int n) {
    boolean numArray[];

    numArray = new boolean[n];
    for(int i = 0; i < n; i++)
        numArray[i] = true;

    int a = 0;

    for(int i = 2; i < Math.sqrt((double)n); i++) {
        if(numArray[i])  {
            for(int j = (int)Math.pow(i, 2); j < n; a++) {
                numArray[j] = false;
                j += (a * i);
            }
        }
    }

    for(int i = 2; i < n; i++) {
        if(numArray[i])
            System.out.println(i);
    }
}

The output it gives me, when i is 15: 当我15岁时,它给我的输出是:

2
3
5
7
8
11
12
13
14

Why are some of these values incorrect? 为什么其中一些值不正确? I believe my error is in how I define and use the bool array. 我相信我的错误在于我如何定义和使用布尔数组。 Thanks! 谢谢!

        for(int j = (int)Math.pow(i, 2); j < n; a++) {
            numArray[j] = false;
            j += (a * i);
        }

should read 应该读

        for(int j = (int)Math.pow(i, 2); j < n; j+=i) {
            numArray[j] = false;
        }

How SoE works is that it takes each number and "deletes" all numbers following it that are divisible by it. SoE的工作方式是获取每个数字并“删除”其后所有可被其整除的数字。 So basically each number x + k*x where k > 0 . 所以基本上每个数字x + k * x其中k> 0 This can be done by simply adding x to the initial x^2 and then adding iteratively x to it. 这可以通过简单地添加x到的初始x ^ 2,然后加入迭代x到它来完成。 Here: 这里:

for(int j = (int)Math.pow(i, 2); j < n; a++) {
    numArray[j] = false;
    j += (a * i);
}

You are not adding x but a*x , so you will skip some numbers as a is being incremented (so you will remove 4,6,10,16 etc, see the pattern? it adds 2,4,6 etc to the initial value) so you should stick with: 您不是在添加x而是a * x ,因此随着a的增加,您将跳过一些数字(因此您将删除4,6,10,16等,请参见模式吗?它将2,4,6等添加到初始值),因此您应该坚持:

for(int j = (int)Math.pow(i, 2); j < n; j+=i) {
    numArray[j] = false;
}

The problem is at line 问题出在线上

 j += (a * i);

In loop, this statement gradually multiplies the j by a*i and add it with j.So replace above line with, 在循环中,此语句逐渐将j乘以a * i 并将其与j相加。

 j = (a * i);

It will work. 它会工作。 And yes,initialize 是的,初始化

a=2

because we don't want numarray[0] or numarray[1] to initialize or use. 因为我们不希望numarray [0]或numarray [1]初始化或使用。 Do comment if any query. 如果有任何疑问,请发表评论。 Thanks 谢谢

This doesn't directly address your question, but since it's already been answered, I don't see any point in repeating it. 这不会直接解决您的问题,但是由于已经回答了问题,因此我认为重复进行没有任何意义。 Looking at your code, though, I suggest using integer multiplication instead of Math.pow and Math.sqrt to get slightly better performance such as: 不过,查看您的代码,我建议使用整数乘法而不是Math.powMath.sqrt来获得更好的性能,例如:

for(int i = 2; i*i < n; i++) {
    if(numArray[i])  {
        for(int j = i*i; j < n; j += i) {
            numArray[j] = false;
        }
    }
}

Admittedly these calls will only be made once per iteration of the outer loop, so the improvement may not be very dramatic. 不可否认,这些调用只会在外循环的每个迭代中进行一次,因此改进可能不会非常显着。 But, calling Math.pow and Math.sqrt are likely to be much more compute intensive than a single integer multiplication. 但是,调用Math.powMath.sqrt可能比单个整数乘法具有更高的计算强度。 Also, if Java performs sufficiently sophisticated optimization, i*i may only get computed once and used in both places saving even more compute cycles. 同样,如果Java执行足够复杂的优化,则i*i可能只被计算一次,并且在两个地方都使用,从而节省了更多的计算周期。 There's also no risk of integer overrunning in this case since i*i is bounded above by the integer n . 在这种情况下,也没有整数溢出的风险,因为i*i在上面受到整数n

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM