簡體   English   中英

算法:使用Eratosthenes篩選列出所有素數

[英]Algorithm: List all prime number using Sieve of Eratosthenes

我已經實現Sieve of Eratosthenes用於查找從1到n的素數列表。 我的代碼適用於從1到10,000的輸入,但我得到以下值> 100,000:

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

我能夠找到問題,當我正在進行i * i時它處於for循環中,因為它已經超出Integer范圍( Integer.MAX_VALUE ),但我找不到解決方案。 有人可以建議我可以做些什么改變我也很感激有人建議我在這個實現中提高效率嗎?

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);
    }
}

從本質上講, for(int j = i * i; ...循環是為了越過i所有倍數。只有從i * i開始交叉才有意義,因為所有較小的倍數已經被較小的除數划掉了。

至少有兩種方法可以從這里開始。

首先,你可以從i * 2而不是i * i 這將擺脫溢出。 從糟糕的一面來看,篩子的復雜性將從O(n log log n)增長到O(n log n)。

其次,您可以檢查i * i是否已經過多,如果是,則完全跳過循環。 回想一下,如果沒有溢出發生,那么它本質上是跳過的,因為i大於nodes.length平方根。 例如,只需在循環之前添加if (i * 1L * i < nodes.length)

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

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM