简体   繁体   中英

Segmented Sieve of Eratosthenes - Java

So I was trying to implement Segmented Sieve of Eratosthenes in Java and this is the best I could do. When I run it, it gives no errors but it doesn't return anything, despite me added "System.out.println" at the end to print out all the remaining primes. Thanks in advance for the recommendations

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();
    }
  }

There were three distinct problems with your implementation. The first issue was that you were assigning v[i] to true in a condition

if(v[i]=true)

Then there were a few off-by-one errors in the termination condition of the for loops, specifically

for (...; i<=m; ...)

instead of

for (...; i<m; ...)

And then lastly, something was off in your math for the the following

int start = (n/primes[i])*3;
for(int j=start+i;j<=m;j=j+i)
    flags[j]=false;

I'm sure it was a small fix, but I couldn't figure it out so I just wrote my own

int start = n + (-n % primes[i]);
for(int j=start;j<m;j+=primes[i])
    flags[j]=false;

Additionally, I made a few small changes to your sieve to speed things up. Rather than checking every number following a prime modulo said prime, I start at prime^2 (where ^ denotes exponentiation) and increment by prime , only flagging multiples with no wasted checks.

Original

primes[counter]=i;
counter=counter+1;
for(int j=i+1;j<=(int)Math.sqrt(m);j++)
{
    if(j%i==0)
    {
        v[j]=false;
    }
}

Optimized

primes[counter++]=i;
for(int j=i*i;j<=(int)Math.sqrt(m);j+=i)
{
    v[j]=false;
}

Put together-

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();
    }
}

Output for n = 800 and m == 1000 for example

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

You have never ending cycle in the following line:

for(int j=start+i;j<=m;j=j+i)

as variables i , j and start always equal 0.

Learn to debug your programs, it will help you a lot ;)

ps keep your code clean, use spaces in expressions like i = n; i < m; instead of i=n;i

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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