Finding prime numbers with the Sieve of Eratosthenes (Originally: Is there a better way to prepare this array?)

前端 未结 13 1485
攒了一身酷
攒了一身酷 2020-12-02 23:38

Note: Version 2, below, uses the Sieve of Eratosthenes. There are several answers that helped with what I originally asked. I have chosen the Sieve of Era

相关标签:
13条回答
  • 2020-12-03 00:01

    Now that you've got a basic sieve in place, note that the inner loop need only continue until temp[i]*temp[i] > prime.

    0 讨论(0)
  • 2020-12-03 00:06

    Restructure your code. Throw out the temporary array, and instead write function that just prime-tests an integer. It will be reasonably fast, since you're only using native types. Then you can, for instance, loop and build a list of integers that are prime, before finally converting that to an array to return.

    0 讨论(0)
  • 2020-12-03 00:07

    ArrayList<> Sieve of Eratosthenes

    // Return primes less than limit
    static ArrayList<Integer> generatePrimes(int limit) {
        final int numPrimes = countPrimesUpperBound(limit);
        ArrayList<Integer> primes = new ArrayList<Integer>(numPrimes);
        boolean [] isComposite    = new boolean [limit];   // all false
        final int sqrtLimit       = (int)Math.sqrt(limit); // floor
        for (int i = 2; i <= sqrtLimit; i++) {
            if (!isComposite [i]) {
                primes.add(i);
                for (int j = i*i; j < limit; j += i) // `j+=i` can overflow
                    isComposite [j] = true;
            }
        }
        for (int i = sqrtLimit + 1; i < limit; i++)
            if (!isComposite [i])
                primes.add(i);
        return primes;
    }
    

    Formula for upper bound of number of primes less than or equal to max (see wolfram.com):

    static int countPrimesUpperBound(int max) {
        return max > 1 ? (int)(1.25506 * max / Math.log((double)max)) : 0;
    }
    
    0 讨论(0)
  • 2020-12-03 00:08

    The easiest solution would be to return some member of the Collections Framework instead of an array.

    0 讨论(0)
  • 2020-12-03 00:10

    I have a really efficient implementation:

    1. we don't keep the even numbers, therefore halving the memory usage.
    2. we use BitSet, requiring only one bit per number.
    3. we estimate the upper bound for number of primes on the interval, thus we can set the initialCapacity for the Array appropriately.
    4. we don't perform any kind of division in the loops.

    Here's the code:

    public ArrayList<Integer> sieve(int n) {
        int upperBound = (int) (1.25506 * n / Math.log(n));
        ArrayList<Integer> result = new ArrayList<Integer>(upperBound);
        if (n >= 2)
            result.add(2);
    
        int size = (n - 1) / 2;
        BitSet bs = new BitSet(size);
    
        int i = 0;
        while (i < size) {
            int p = 3 + 2 * i;
            result.add(p);
    
            for (int j = i + p; j < size; j += p)
                bs.set(j);
    
            i = bs.nextClearBit(i + 1);
        }
    
        return result;
    }
    
    0 讨论(0)
  • 2020-12-03 00:12

    Are you using Java 1.5? Why not return List<Integer> and use ArrayList<Integer>? If you do need to return an int[], you can do it by converting List to int[] at the end of processing.

    0 讨论(0)
提交回复
热议问题