简体   繁体   English

Eratosthenes的分段筛-Java

[英]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. 所以我试图用Java实现Eratosthenes的分段筛,这是我所能做的最好的。 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. 当我运行它时,它没有任何错误,但是它没有返回任何内容,尽管我在最后添加了“ System.out.println”以打印出所有剩余的质数。 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 第一个问题是您在条件中将v[i]分配为true

if(v[i]=true)

Then there were a few off-by-one errors in the termination condition of the for loops, specifically 然后在for循环的终止条件中存在一些错误的错误,特别是

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. 我没有检查素数模数质数之后的每个数字,而是从prime^2 (其中^表示幂)开始,并按prime递增,仅标记多个倍数而没有浪费的检查。

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 例如, n = 800m == 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

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. 作为变量ijstart始终等于0。

Learn to debug your programs, it will help you a lot ;) 学习调试程序,它将对您有很大帮助;)

ps keep your code clean, use spaces in expressions like i = n; ps保持代码干净,在表达式中使用空格,例如i = n; i < m; 我<m; instead of i=n;i 而不是i = n; i

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

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