递归Factoring with Java,处理StackOverflow

时间:2013-04-14 09:23:54

标签: java recursion stack-overflow

我需要编写一个方法来递归地将数字计算到1234567890,我的当前应用程序只能在抛出StackOverflowError之前处理小数字。我知道我的问题是太多的递归调用,但我无法弄清楚如何减少我的调用次数。

它需要递归。

我认为解决方案与算法背后的数学有关。我已经看过不同的迭代解决方案了,我似乎无法用更少的调用来递归执行它。代码:

public static boolean isPrime(int input, int i) {
    if (i <= 2) {
        return true;
    }
    if (input % i != 0) {
        return isPrime(input, i-1);
    } else {
        factors(input, i);
        return false;
    }
}
public static void factors(int input, int i) {
    if (i <= 1) {
        System.out.printf(" %d", 1);
    } else {
        if (input % i == 0) {
            System.out.printf(" %d", i);
        }
        factors(input, i - 1);
    }
}

由以下人员开始:

System.out.println("What integer would you like to factor?");
    num1 = scan.nextInt();
    if(isPrime(num1, num1 - 1)){
        System.out.println("Input is a prime number");
    } else {
        System.out.println(" factors\nInput isn't a prime number.");
    }

5 个答案:

答案 0 :(得分:2)

将您的因子方法更改为非递归(如果不需要递归)

 public static void factors(int input, int i) {
     for(int j = i; j >= 1; j--) {
         if (input % j == 0)
             System.out.println(j);
     } 
}

已编辑:以下内容是解决此问题的递归方法。

public void isPrime(int num1)
{
int count=countFactors(num1);
if(count==0)
System.out.println("No is prime");
}

public int countFactors(int num,int i)
{

if(i>num/2)return 0;
if(num%i==0)
{
System.out.println(i);
return 1+countFactors(num,i+1);
}

}

答案 1 :(得分:1)

我认为它需要递归的原因是因为它是一个家庭作业问题。因此,我不会告诉你如何做,而是你的数学有什么问题。您的算法看起来部分正确,除了(a)您忘记按您找到的每个因素划分'n',以及(b)您正在寻找从大数下来而不是小数字的因子。最好先启动2并计算到sqrt(n),尽管这不会解决堆栈溢出问题。

您需要在循环中查找因子并保留使用递归(如果您确实需要使用它),以便在除去素数因子后对剩余数量进行分解。因为你不想通过一个6位数的素数,然后需要100万个级别的堆栈来证明它没有因素。即,这需要在一个简单的循环而不是递归:

return isPrime(input,i-1);

......这可以是递归的:

因素(输入,i);

答案 2 :(得分:0)

增加java中的堆栈大小。 你可以搜索如何增加堆栈大小

答案 3 :(得分:0)

您似乎用于素性检查的算法是trial division algorithm

有一些other methods,但是,按照这个策略,有一个命题说明你只需要检查 n 的平方根,其中 n 是您的input。此外,您的谓词不会正确处理负整数(返回true)。

因此,在第一种方法中,您的算法将是:

public static boolean isPrime(int n) {
    if (n < 2) { return false; }
    return helper_isPrime(n, 2, (int) Math.sqrt(n));
}

其中:

private static boolean helper_isPrime(int n, int i, int max) {
    if (i > max) { return true; }
    if (n % i == 0) { return false; }
    return helper_isPrime(n, i+1, max);
}

分离两种方法隔离了n < 2的测试。请注意,n将保持不变,因此测试只需要在流程开始时执行一次。

此外,保理因素被遗忘。在我看来,应该从外面询问,如下:

System.out.println("What integer would you like to factor?");
num1 = scan.nextInt();
if(isPrime(num1)){
    System.out.println("Input is a prime number");
} else {
    System.out.println("Input isn't a prime number.");
    int[] fac = factor(n);
    System.out.println("Factors: " + fac.toString());
}

factor将成为您最喜欢的因子算法。因子分解算法可能会发现它是使用素数执行的最坏情况,但是,由于测试已经进行,并且由于算法仅在数字素数时被调用,因此这个场景赢了“发生了。

答案 4 :(得分:0)

您可以使用

来使用尾调用优化(Java不适合您)
public static void factors(int input, int i) {
    while(i > 1) {
        if (input % i == 0) {
            System.out.printf(" %d", i);
        }
        i = i - 1;
    }
    System.out.printf(" %d", 1);
}

除了你当然不再做递归。