簡體   English   中英

Java遞歸中的堆棧溢出錯誤

[英]Stack overflow error in Java recursion

我正在嘗試實現一個返回200萬以下所有素數之和的代碼。 我有一個isPrime(int x)方法,如果數字是素數,則返回true。 這里是:

public static boolean isPrime(int x) {

        for (int i = 2; i < x; i++) {

            if (x % i == 0) {
                return false;
            }

        }
        return true;

    }

另一種方法,我試圖遞歸地實現,只有一定數量,超過該數字,我得到一個堆棧溢出錯誤。 我得到的最高代碼是10,000。

這里是:

public static int sumOfPrimes(int a) {

    if (a < 2000000) {  //this is the limit

        if (isPrime(a)) {
            return a + sumOfPrimes(a + 1);

        } else {
            return sumOfPrimes(a + 1);
        }

    }
    return -1;
}

那么為什么當數字變大時我會得到堆棧溢出錯誤,我該如何處理呢? 另外,你通常如何處理為這么大的數字編寫代碼? IE:像這樣的正常數字操作但是對於更大的數字? 我遞歸地寫了這個,因為我認為它會更有效但它仍然無法工作。

你的isPrime函數是低效的,它不必轉到x ,它足以轉到x的平方根。

但這並不是您的解決方案不起作用的原因。 你不能有100萬的遞歸深度。

我會迭代地解決這個問題,使用eratosthenes篩子並在結果boolean數組上循環。

通常,如果您仍想使用遞歸,則可以使用尾遞歸。 在遞歸中,每個函數調用都會將一些數據推送到堆棧,這是有限的,因此會產生堆棧溢出錯誤。 在尾遞歸中,你不會向堆棧推送任何東西,因此不會拋出異常。

基本上你只需要將先前計算的數據作為參數發送,而不是將它放在堆棧上。

所以:

function(int x) {
    // end condition
    return function(x - 1) + x;
}

尾部遞歸會

function (int max, int curr, int prev, int sum) {
    if (curr > max) 
        return sum;

    return function (max, curr + 1, curr, sum + curr)
}

請記住,這只是偽代碼而不是真正的java代碼,但與java代碼足夠接近。

有關詳細信息,請查看

什么是尾遞歸?

使用Eratosthenes篩選: -

以下是通過Eratosthenes方法找到小於或等於給定整數n的所有素數的算法:

1)創建從2到n的連續整數列表:(2,3,4,...,n)。
2)最初,讓p等於2,即第一個素數。
3)從p開始,以p為增量進行計數,並在列表中將每個數字標記為大於p本身。 這些數字將是2p,3p,4p等; 請注意,其中一些可能已被標記。
4)在列表中找到未標記的第一個大於p的數字。 如果沒有這樣的號碼,請停止。 否則,讓p現在等於這個數字(這是下一個素數),並從步驟3開始重復。

public static void main(String[] args) {
    int n = 30;
    System.out.printf("Following are the prime numbers below %d\n", n);
    SieveOfEratosthenes(n);
}

static void markMultiples(boolean arr[], int a, int n)
{
    int i = 2, num;
    while ( (num = i*a) <= n )
    {
        arr[ num-1 ] = true; // minus 1 because index starts from 0.
        ++i;
    }
}

// A function to print all prime numbers smaller than n
static void SieveOfEratosthenes(int n)
{
    // There are no prime numbers smaller than 2
    if (n >= 2)
    {
        // Create an array of size n and initialize all elements as 0
        boolean[] arr=new boolean[n];
        for(int index=0;index<arr.length-1;index++){
            arr[index]=false;
        }

        for (int i=1; i<n; ++i)
        {
            if ( arr[i] == false )
            {
                //(i+1) is prime, print it and mark its multiples
                System.out.printf("%d ", i+1);
                markMultiples(arr, i+1, n);
            }
        }
    }
}

Output:-
Following are the prime numbers below 30
2 3 5 7 11 13 17 19 23 29 

暫無
暫無

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

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