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

时间:2016-09-23 08:08:58

标签: java algorithm list primes

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

首先尝试:因为大于2的所有素数都是奇数,所以我首先生成一个以3开始的奇数列表,称为allComposite。然后我生成一个名为allComposite的所有复合数字列表。然后,我从allOddNums中移除/** 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) + " "); } } } 中的所有数字以获取素数。这是我的代码:

sieve of Eratosthenes

在这种情况下,当我需要生成一些素数时,它可以正常工作。但是,如果我要生成直到3000000它就会让我失望(耗尽内存)。

第二次尝试:我在网上搜索并找到一个名为/** 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; } } } } 的算法。然后我首先生成2,3,5,7,9 ...(所有奇数+ 2),然后我删除3之后的每第3个数字和5之后的每5个数字。代码如下:

/** 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;
        }
      }
    }
  }
}

这仍然不能完成任务,因为它也会耗尽内存。

第3次尝试: 我试图从1到3000000生成,然后删除每个数字是素数和另一个数的乘积。代码如下:

/** new approach to find prime numbers
  * Tony
  */
import java.util.*;

public class PrimeG {

  /** isPrime
    * To determine whether a number is prime by dividing the candidate number by each prime in that list
    */
  static List<Long> primes = new ArrayList<Long> ();

  private static void isPrime(long n) {
    boolean condition = true;
    for (int i = 0; i < primes.size(); i++) {
      if (n % primes.get(i) == 0) {
        condition = condition && false;
      }
    }
    if (condition) {
      findNextPrime(n);
    }
  }

  /** findNextPrime
    * expand the list of prime numbers 
    */
  private static void findNextPrime(long n) {
    primes.add(n);
  }





  public static void main(String[] args) {
    primes.add((long)2);
    primes.add((long)3);
    primes.add((long)5);
    primes.add((long)7);

    for (int i = 8; i < 3000000; i++) {
      isPrime(i);
      System.out.printf("%s", primes);
    }


  }
}

它仍然让我失望,好吧猜测3000000真是个大数字吧?是否有任何简单而精彩的菜鸟友好方式来产生低于3000000的素数? THX!

第四次尝试: @jsheeran这个代码下面是你的答案意味着什么?当我达到1093时,它变得越来越慢,我的IDE仍然崩溃。 Plz告诉我,如果我误解你的方法,那么!

adb logcat *:S ReactNative:V ReactNativeJS:V

4 个答案:

答案 0 :(得分:3)

修复了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);
    }
}

答案 1 :(得分:2)

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

答案 2 :(得分:1)

在您的情况下,内存不是问题。可以在函数的堆栈帧内定义大小为n = 3000000的数组。实际上,可以在函数内安全地定义大小为10 ^ 8的数组。如果您需要更多,则将其定义为gloabal变量(实例变量)。来到您的代码后,您的第三个代码中会出现IndexOutOfBoundsException。您需要检查数字的因子,直到sqrt(n)。因子成对存在一个因子<=sqrt(n)和其他>=sqrt(n)。所以你可以优化Eratosthenes算法的筛子。以下是one wonderful tutorial关于各种筛选优化的链接。

答案 3 :(得分: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);
  }
}