我正在编写一个程序,使用良好的'Eratosthenes筛选算法(虽然有一个转折)来查找素数。为了将所需的字节数组的大小减半,我不代表任何偶数,并坚持使用奇数(通过整数除以2计算它们在数组中的位置)。
但是,我有一个问题。我的程序似乎并不认为17或113为素数,尽管它们确实是素数。这是我的代码:public class Eratosthes {
byte[] checklist;
int range;
public EratosthesConcurrent(int range) {
this.range = range/2;
this.checklist = new byte[this.range];
this.initAllChecked();
this.findPrimesSeq();
this.printPrimes();
}
private void initAllChecked(){
for(int i = 1; i < checklist.length; i++){
checklist[i] = 1;
}
}
private void crossOut(int i){
checklist[i/2] = 0;
}
private void findPrimesSeq(){
int curr = 3;
outer: while(curr < range*2){
for(int i = curr*curr; i < range*2; i+=2*curr){
if(i != curr && i%curr == 0){
if(i == 113){
System.out.println(curr);
}
crossOut(i);
}
}
secondLoop: for(int i = curr; i < range*2; i++){
if(checklist[i/2] == 1 && curr != i){
curr = i;
break secondLoop;
} else if(i == range*2-1 || i == range*2-2){ //Should be changed, might miss the last prime
break outer;
}
}
}
}
public void printPrimes(){
for(int i = 1; i < range; i++){
if(checklist[i] == 1){
System.out.println("Prime found: " + ((i*2)+1));
}
}
}
}
将以下内容添加到crossOut方法不会产生任何输出:
if(i == 17 || i == 113){
System.out.println("Found one of the numbers");
}
这对我来说很奇怪,因为该程序的打印输出排除了17和113,因此不会检查它们的任何倍数。这给我留下了一个字节数组,其中检查了所有素数......以及17或113的任何倍数。
如果有人能在我的程序中找到错误,我会很高兴 - 我自己一直在调试它几个小时,没有结果。提前谢谢。
答案 0 :(得分:2)
问题似乎是你没有检查除以2。
您在某个时刻(特别是crossOut(16)
的倍数)呼叫4
,它会超出17
的相应值。同样,112
会导致113
划掉。
变化:
if (i != curr && i % curr == 0) {
为:
if (i % 2 != 0 && i != curr && i % curr == 0) {
并且这两个都被打印为素数。
另外,我有点担心这个循环究竟在做什么 - 我没有太详细地看输出,虽然它实际上似乎是所有的素数,但我想你应该循环多次curr
的{{1}},第一个是2*curr
(不是curr*curr
),是curr
(不是2*curr
)之间的增量,虽然我不是说你是什么这样做是不正确的,因为我需要更多的时间来准确理解你的代码是如何解决这个问题的。
答案 1 :(得分:0)
for(int i = curr*curr; i < range*2; i+=2*curr){
第一个值= 9然后转到15
curr = 3 - 3 * 3 = 9
i + = 2 * curr = 9 + 6
伪:
outerNum = sqrt[range]
array[boolean] size of range
array[0 & 1] = false
for i = 2 to outernum
for j = i to range
if j % i != 0
array[j] = false
for i = array[boolean] length
print if array[i] = true
如果有任何错误,请记忆,请原谅。