我使用伪代码实现了Java中的Eratosthenes Sieve:
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);
}
}
当我15岁时,它给我的输出:
2
3
5
7
8
11
12
13
14
为什么其中一些值不正确?我相信我的错误在于如何定义和使用bool数组。谢谢!
答案 0 :(得分:4)
for(int j = (int)Math.pow(i, 2); j < n; a++) {
numArray[j] = false;
j += (a * i);
}
应该阅读
for(int j = (int)Math.pow(i, 2); j < n; j+=i) {
numArray[j] = false;
}
答案 1 :(得分:2)
SoE的工作原理是它接受每个数字并“删除”其后面可被其整除的所有数字。所以基本上每个数字 x + k * x 其中 k&gt; 0 即可。这可以通过简单地将 x 添加到初始 x ^ 2 ,然后迭代地添加 x 来完成。这里:
for(int j = (int)Math.pow(i, 2); j < n; a++) {
numArray[j] = false;
j += (a * i);
}
您没有添加 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;
}
答案 2 :(得分:0)
问题在于
j += (a * i);
在循环中,这个陈述逐渐将j乘以a * i和 add 它与j.So替换上面的行,
j = (a * i);
它会起作用。 是的,初始化
a=2
因为我们不希望numarray [0]或numarray [1]初始化或使用。 如果有任何查询请做评论。感谢
答案 3 :(得分:0)
这并没有直接解决你的问题,但由于它已经得到了解答,我认为重复它没有任何意义。不过,看一下你的代码,我建议使用整数乘法而不是Math.pow
和Math.sqrt
来获得更好的性能,例如:
for(int i = 2; i*i < n; i++) {
if(numArray[i]) {
for(int j = i*i; j < n; j += i) {
numArray[j] = false;
}
}
}
不可否认,这些调用只会在外循环的每次迭代中进行一次,因此改进可能不会非常显着。但是,调用Math.pow
和Math.sqrt
可能比单个整数乘法更加计算密集。此外,如果Java执行足够复杂的优化,i*i
可能只计算一次并在两个地方使用,从而节省更多的计算周期。在这种情况下也没有整数超限的风险,因为i*i
的上限是整数n
。