简体   繁体   中英

Algorithm: List all prime number using Sieve of Eratosthenes

I have implemented Sieve of Eratosthenes for finding the list of prime number from 1 to n. My code is working fine for inputs from 1 to 10,000 but I am getting following for values >100,000:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -2146737495
        at SieveOfEratosthenes.main(SieveOfEratosthenes.java:53)

I am able to find the issue, which is in the for loop when I am doing i * i as it is going out of Integer range ( Integer.MAX_VALUE ), but I could not find the solution. Can someone suggest me what changes can be done also I appreciate if someone suggest me any improvement for efficiency in this implementation?

public class SieveOfEratosthenes {

    public static void main(String[] args) {

        Integer num = Integer.parseInt(args[0]);
        Node[] nodes = new Node[num + 1];

        for(int i = 1; i < nodes.length; i++) {

            Node n = new Node();
            n.setValue(i);
            n.setMarker(true);

            nodes[i] = n;
        }

        for(int i = 1; i < nodes.length; i++) {

            if(nodes[i].getMarker() && nodes[i].getValue() > 1) {
                System.out.println("Prime " + nodes[i].getValue());
            } else {
                continue;
            }

            for(int j = i * i; j < nodes.length
                                    && nodes[i].getMarker(); j = j + i) {
                nodes[j].setMarker(false);
            }
        }

        System.out.println(l.size());

    }
}

class Node {

    private int value;
    private boolean marker;

    public void setValue(int value) {
        this.value = value;
    }

    public int getValue() {
        return this.value;
    }

    public void setMarker(boolean marker) {
        this.marker = marker;
    }

    public boolean getMarker() {
        return this.marker;
    }

    public String toString() {
        return ("Value : " + marker + " value " + value);
    }
}

Essentially, the for(int j = i * i; ... loop is to cross out all multiples of i . It makes sense only to cross out starting from i * i , since all lesser multiples are already crossed out by their lesser divisors.

There are at least two ways to go from here.

First, you can start crossing out from i * 2 instead of i * i . This will get rid of the overflow. On the bad side, the complexity of the sieve would grow from O(n log log n) to O(n log n) then.

Second, you can check whether i * i is already too much, and if it is, skip the loop completely. Recall that it is essentially skipped anyway for i greater than the square root of nodes.length if no overflow occurs. For example, just add an if (i * 1L * i < nodes.length) before the loop.

    for(int i = 1; i < nodes.length; i++) {
        if(nodes[i].getMarker() && nodes[i].getValue() > 1) {
            System.out.println("Prime " + nodes[i].getValue());
        } else {
            continue;
        }

TO

int limit = 2 << 14;
for(int i = 1; i < nodes.length; i++) {
    if(nodes[i].getMarker() && nodes[i].getValue() > 1 && i <= 2 << 15) {
        System.out.println("Prime " + nodes[i].getValue());
        if (i > limit) {
            continue;
        }
    } else {
        continue;
    }

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