[英]Segmented Sieve of Eratosthenes - Java
所以我試圖用Java實現Eratosthenes的分段篩,這是我所能做的最好的。 當我運行它時,它沒有任何錯誤,但是它沒有返回任何內容,盡管我在最后添加了“ System.out.println”以打印出所有剩余的質數。 預先感謝您的建議
public class SegmentedSieveofEratosthenes {
public static void main(String[] args) throws java.lang.Exception {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
boolean[] v = new boolean[1000000];
int[] primes = new int[1000000];
//counter for the primes vector
int counter = 0;
for(int i=2;i<=(int)Math.sqrt(m);i++)
{
v[i]=true;
}
for(int i=2;i<=(int)Math.sqrt(m);i++)
{
if(v[i]=true)
{
primes[counter]=i;
counter=counter+1;
for(int j=i+1;j<=(int)Math.sqrt(m);j++)
{
if(j%i==0)
{
v[j]=false;
}
}
}
}
boolean[] flags = new boolean[1000000];
for(int i=n;i<=m;i++)
{
flags[i]=true;
}
for(int i=0;i<counter;i++)
{
int start = (n/primes[i])*3;
for(int j=start+i;j<=m;j=j+i)
flags[j]=false;
}
for(int i=n;i<=m;i++)
if(flags[i]==true)
System.out.println(i);
in.close();
}
}
您的實現存在三個明顯的問題。 第一個問題是您在條件中將v[i]
分配為true
if(v[i]=true)
然后在for循環的終止條件中存在一些錯誤的錯誤,特別是
for (...; i<=m; ...)
代替
for (...; i<m; ...)
最后,以下內容在您的數學上有些錯誤
int start = (n/primes[i])*3;
for(int j=start+i;j<=m;j=j+i)
flags[j]=false;
我敢肯定這是一個小問題,但是我無法弄清楚,所以我只寫了自己的
int start = n + (-n % primes[i]);
for(int j=start;j<m;j+=primes[i])
flags[j]=false;
另外,我對您的篩子做了一些小改動,以加快處理速度。 我沒有檢查素數模數質數之后的每個數字,而是從prime^2
(其中^
表示冪)開始,並按prime
遞增,僅標記多個倍數而沒有浪費的檢查。
原版的
primes[counter]=i;
counter=counter+1;
for(int j=i+1;j<=(int)Math.sqrt(m);j++)
{
if(j%i==0)
{
v[j]=false;
}
}
優化
primes[counter++]=i;
for(int j=i*i;j<=(int)Math.sqrt(m);j+=i)
{
v[j]=false;
}
放在一起-
import java.util.Scanner;
import java.util.Arrays;
public class SegmentedSieveofEratosthenes {
public static void main(String[] args) throws java.lang.Exception {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
boolean[] v = new boolean[1000000];
int[] primes = new int[1000000];
//counter for the primes vector
int counter = 0;
for(int i=2;i<=(int)Math.sqrt(m);i++)
{
v[i]=true;
}
for(int i=2;i<=(int)Math.sqrt(m);i++)
{
if(v[i])
{
primes[counter++]=i;
for(int j=i*i;j<=(int)Math.sqrt(m);j+=i)
{
v[j]=false;
}
}
}
boolean[] flags = new boolean[1000000];
for(int i=n;i<m;i++)
{
flags[i]=true;
}
for(int i=0;i<counter;i++)
{
int start = n + (-n % primes[i]);
for(int j=start;j<m;j+=primes[i])
if (j != primes[i])
flags[j]=false;
}
for(int i=n;i<m;i++)
if(flags[i])
System.out.println(i);
in.close();
}
}
例如, n = 800
和m == 1000
輸出
809
811
821
823
827
829
839
853
857
859
863
877
881
883
887
907
911
919
929
937
941
947
953
967
971
977
983
991
997
您永遠不會在以下行中結束循環:
for(int j=start+i;j<=m;j=j+i)
作為變量i , j和start始終等於0。
學習調試程序,它將對您有很大幫助;)
ps保持代碼干凈,在表達式中使用空格,例如i = n; 我<m; 而不是i = n; i
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.