[英]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.