如何在java中生成大量素数?

如何在java中生成大量素数?,java,algorithm,list,primes,Java,Algorithm,List,Primes,为了解决一个问题,我必须生成一个从1到3000000的素数列表,所以我尝试了几种方法来解决这个问题,不幸的是,所有方法都失败了 第一次尝试:因为所有大于2的素数都是奇数,所以我首先生成一个以3开头的奇数列表,名为allodnums。然后我生成一个名为allComposite的所有组合编号的列表。然后我从allodnums中删除allComposite中的所有数字以获得素数。这是我的密码: /** Prime Numbers Generation * Tony */ import java

为了解决一个问题,我必须生成一个从1到3000000的素数列表,所以我尝试了几种方法来解决这个问题,不幸的是,所有方法都失败了

第一次尝试:因为所有大于2的素数都是奇数,所以我首先生成一个以3开头的奇数列表,名为
allodnums
。然后我生成一个名为
allComposite
的所有组合编号的列表。然后我从
allodnums
中删除
allComposite
中的所有数字以获得素数。这是我的密码:

/** Prime Numbers Generation
  * Tony
  */
import java.util.*;

public class PrimeNumG {
  public static void main(String[] args) {

    List <Long> allOddNums = new ArrayList<Long>();
    for (long i = 3; i < 200; i += 2) {
      allOddNums.add(i);
    }

    // composite number generator:
    List <Long> allComposite = new ArrayList<Long>();
    for (long a = 2; a < Math.round(Math.sqrt(3000000)); a += 2) {
      for (long b = 2; b < Math.round(Math.sqrt(3000000)); b += 2) {
        allComposite.add(a*b);
      }
    }

    // remove duplicated:
    Set <Long> hs = new HashSet<Long>();
    hs.addAll(allComposite);
    allComposite.clear();
    allComposite.addAll(hs);

    // remove all composite from allRealNums = allPrime
    allOddNums.removeAll(allComposite);
    allOddNums.add(0, (long)2);

    System.out.printf("%s ", allOddNums);
    Scanner sc = new Scanner(System.in);
    int times = sc.nextInt();

    for (int i = 0; i < times; i++) {
      int index = sc.nextInt();
      System.out.print(allOddNums.get(index) + " ");

    }
  }
}
这仍然无法完成任务,因为它也会耗尽内存

第三次尝试: 我试着从1生成300万,然后去掉每个数是素数和另一个数的乘积。代码如下:

/** Prime Number Generator
  * Tony
  */   
import java.util.*;

public class Solution61 {
  public static void main(String[] args) {
    List<Long> l1 = new ArrayList<Long> ();

    // l1 generator:   3 5 7 9 11 ... 
    for (long d = 3; d < 100; d += 2) {
      l1.add(d);
    }

    l1.add(1, (long)2); // 2 3 5 ...

    removeThird(l1); // rm 3rd after 3

    removeFifth(l1); // rm 5th after 5, now the l1 will be prime number

    Scanner sc = new Scanner(System.in);
    int times = sc.nextInt();
    for (int i = 0; i < times; i++) {
      int index = sc.nextInt();
      System.out.print(l1.get(index) + " ");


    }
  }


  /** removeThird : remove every 3rd number after 3
    * param List | return void
    */
  private static void removeThird(List<Long> l) {

    int i = 1;
    int count = 0;
    while (true) {


      if (count == 3) {
        l.remove(i);
        count = 1;

      }
      i ++;
      count ++;
      if (i > l.size()) {
        break;
      }
    }
  }

  /** removeThird : remove every 5th number after 5
    * param List | return void
    */
  private static void removeFifth(List<Long> l) {

    int i = 2;
    int count = 0;
    while (true) {


      if (count == 5) {
        l.remove(i);
        count = 1;
      }
      i ++;
      count ++;
      if (i > l.size()) {
        break;
      }
    }
  }

}
/** print all the prime numbers less than N
  * Tony
  */

public class primeGenerator {
  public static void main(String[] args) {
    int n = 3000000;
    boolean[] isPrime = new boolean[n];
    isPrime[0] = false; // because 1 is not a prime number

    for (int i = 1; i < n; i++) {
      isPrime[i] = true;
    } // we set 2,3,4,5,6...to true

    // the real number is always (the index of boolean + 1)

    for (int i = 2; i <= n; i++) {
      if (isPrime[i-1]) {
        System.out.println(i);
        for (int j = i * i; j < n; j += i /* because j is determined by i, so the third parameter doesn't mater*/) {
          isPrime[j-1] = false;
        }
      }
    }
  }
}
/**打印所有小于N的素数
*托尼
*/
公共类素数生成器{
公共静态void main(字符串[]args){
整数n=300万;
布尔值[]isPrime=新布尔值[n];
isPrime[0]=false;//因为1不是质数
对于(int i=1;i对于(inti=2;i修复了Eratosthenes筛的实现(您的第三次尝试)。我相信它应该满足您的需求

public static void main (String[] args) throws java.lang.Exception {
    int n = 3000000;

    boolean[] isPrime = new boolean[n+1];
    for (int i = 2; i <= n; i++) {
        isPrime[i] = true;
    }

    for (int factor = 2; factor*factor <= n; factor++) {
        if (isPrime[factor]) {
            for (int j = factor; factor*j <= n; j++) {
                isPrime[factor*j] = false;
            }
        }
    }

    for (int i = 2; i <= n; i++) {
        if (isPrime[i]) System.out.println(i);
    }
}
publicstaticvoidmain(字符串[]args)抛出java.lang.Exception{
整数n=300万;
布尔值[]isPrime=新布尔值[n+1];

对于(inti=2;i修复了Eratosthenes筛的实现(您的第三次尝试)。我相信它应该满足您的需求

public static void main (String[] args) throws java.lang.Exception {
    int n = 3000000;

    boolean[] isPrime = new boolean[n+1];
    for (int i = 2; i <= n; i++) {
        isPrime[i] = true;
    }

    for (int factor = 2; factor*factor <= n; factor++) {
        if (isPrime[factor]) {
            for (int j = factor; factor*j <= n; j++) {
                isPrime[factor*j] = false;
            }
        }
    }

    for (int i = 2; i <= n; i++) {
        if (isPrime[i]) System.out.println(i);
    }
}
publicstaticvoidmain(字符串[]args)抛出java.lang.Exception{
整数n=300万;
布尔值[]isPrime=新布尔值[n+1];

对于(int i=2;i另一种方法是从由2和3组成的素数列表开始。使用一种方法
isPrime(int)
,通过将候选数除以列表中的每个素数来确定一个数是否为素数。定义另一种方法,
findNextPrime()
,它
isPrime()
可以根据需要调用扩展列表。这种方法的开销比维护所有奇数和复合数的列表要低得多。

另一种方法是从由2和3组成的素数列表开始。使用方法
isPrime(int)
通过将候选数字除以列表中的每个素数来确定一个数字是否为素数。定义另一种方法,
findNextPrime()
,它是
isPrime()
可以根据需要调用以扩展列表。这种方法的开销比维护所有奇数和复合数的列表要低得多。

内存在您的情况下不是问题。大小为
n=3000000的数组可以在函数的堆栈框架内定义。实际上,大小为10^8的数组可以在函数内安全地定义。如果y您需要的不仅仅是将其定义为global变量(实例变量)。在您的代码中,第三个代码中有一个
indexootfboundsexception
。您只需要检查一个数字的因子uptill
sqrt(n)
。因子成对存在一个因子
=sqrt(n)
。因此,您可以优化Eratosthenes算法的筛。这里有一个链接,链接到筛的各种优化。

在您的情况下,内存不是问题。大小为
n=3000000的数组可以在函数的堆栈框架内定义。实际上,大小为10^8的数组可以在函数内安全地定义。如果您需要超过t将其定义为global变量(实例变量)。在您的代码中,第三个代码中有一个
indexootfboundsexception
。您只需检查一个数字的因数upall
sqrt(n)
。因数成对存在一个因数
=sqrt(n)
。因此,您可以优化Eratosthenes算法的筛选。这里是有关各种筛选优化的链接。

这可以在几毫秒内生成最多为
整数的素数。最大值
。它也不需要像Eratosthenes方法中的筛选那样占用大量内存

public class Prime {

  public static IntStream generate(int limit) {
    return IntStream.range(2, Integer.MAX_VALUE).filter(Prime::isPrime).limit(limit);
  }

  private static boolean isPrime(int n) {
    return IntStream.rangeClosed(2, (int) Math.sqrt(n)).noneMatch(i -> n % i == 0);
  }
}

这可以在几毫秒内生成最多为
Integer.MAX_VALUE
的素数。它也不需要像Eratosthenes方法中的筛选那样占用内存

public class Prime {

  public static IntStream generate(int limit) {
    return IntStream.range(2, Integer.MAX_VALUE).filter(Prime::isPrime).limit(limit);
  }

  private static boolean isPrime(int n) {
    return IntStream.rangeClosed(2, (int) Math.sqrt(n)).noneMatch(i -> n % i == 0);
  }
}

是的,你看,“我猜3000000真是个大数字,是吧?”不完全是。埃拉托什尼的筛子应该处理得很简单。哦!我知道。这是我在第二次和第三次尝试中使用的方式,但它仍然没有内存。你能看看我在第二次和第三次尝试中的代码,告诉我出了什么问题吗?首先,请看
int j=I*I
=>
int j=2*I
方法不会耗尽内存,前提是它可以分配
isPrime
数组:之后不会分配内存。是的,有。请看。“我猜3000000真是一个大数字,是吧?”不完全是。埃拉托什尼的筛子应该处理得很简单。哦!我知道。这是我在第二次和第三次尝试中使用的方式,但它仍然没有内存。你能看看我在第二次和第三次尝试中的代码,告诉我出了什么问题吗?首先,请看
int j=I*I
=>
int j=2*I
如果代码可以分配< <代码> ISPrime数组:此后没有分配内存,方法也不会用完。也考虑使用IF内存是个问题。嗯……我不知道……它仍然变得越来越慢,然后我不得不强制退出IDE。还考虑使用IF内存是个问题。嗯……我不知道……它仍然能获得SL。如果您在sieve实现中包含了一些解决问题的代码,或者提供了您建议的改进算法的简要示例,那么这将对您的答案有所帮助。如果您在sieve实现中包含了一些解决问题的代码,或者提供了一个您建议的改进算法的简要示例