java程序中的stackoverflowerr

java程序中的stackoverflowerr,java,recursion,stack-overflow,Java,Recursion,Stack Overflow,我试图解决一个问题,它要求找到最小的素数回文,它位于给定的数字之后,这意味着如果输入是24,那么输出将是101,因为它是24之后的最小数,同时也是素数和回文 现在,我的代码可以完美地处理小值,但当我插入543212之类的东西作为输入时,第20行出现了StackOverflower错误,第24行出现了StackOverflower错误的多个实例。这是我的密码: package nisarg; import java.util.Scanner; public class Chef_prime_pa

我试图解决一个问题,它要求找到最小的素数回文,它位于给定的数字之后,这意味着如果输入是24,那么输出将是101,因为它是24之后的最小数,同时也是素数和回文

现在,我的代码可以完美地处理小值,但当我插入543212之类的东西作为输入时,第20行出现了StackOverflower错误,第24行出现了StackOverflower错误的多个实例。这是我的密码:

package nisarg;
import java.util.Scanner;

public class Chef_prime_palindromes {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        long num = input.nextLong();
        isPalindrome(num + 1);
    }

    public static boolean isPrime(long num) {
        long i;
        for (i = 2; i < num; i++) {
            if (num % i == 0) {
                return false;
            }
        }
        return true;
    }

    public static void isPalindrome(long num) {
        String word = Long.toString(num);
        int i;
        for (i = 0; i < word.length() / 2; i++) {
            if (word.charAt(i) != word.charAt(word.length() - i - 1)) {
                isPalindrome(num + 1);
            }
        }
        if (i == word.length() / 2) {
            if (isPrime(num)) {
                System.out.println(num);
                System.exit(0);
            } else {
                isPalindrome(num + 1);
            }
        }
    }
}
在每次递归调用中都会创建一个新的字符串对象,并将其放在堆栈上,在方法中创建的所有变量都存储在堆栈上,直到您离开该方法为止,这对于足够深的递归来说会使JVM到达分配的堆栈空间的末尾

我通过将字符串对象放在一个单独的方法中改变了它的局部性,从而减少了它的局部性,并限制了它的创建和销毁,将堆栈空间释放到一个递归调用中

package com.company;

import java.util.Scanner;

public class Chef_prime_palindromes {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        long num = input.nextLong();
        isPalindrom(num + 1);
    }

    public static boolean isPrime(long num) {
        long i;
        for (i = 2; i < num; i++) {
            if (num % i == 0) {
                return false;
            }
        }
        return true;
    }

    private static void isPalindrom(long num) {
        for (; ; ) {
            if (isPalindrome(num)) {
                if (isPrime(num)) {
                    System.out.println(num);
                    System.exit(0);
                } else {
                    num++;
                }
            } else {
                num++;
            }
        }
    }

    public static boolean isPalindrome(long num) {
        String string = String.valueOf(num);
        return string.equals(new StringBuilder(string).reverse().toString());
    }
}
在每次递归调用中都会创建一个新的字符串对象,并将其放在堆栈上,在方法中创建的所有变量都存储在堆栈上,直到您离开该方法为止,这对于足够深的递归来说会使JVM到达分配的堆栈空间的末尾

我通过将字符串对象放在一个单独的方法中改变了它的局部性,从而减少了它的局部性,并限制了它的创建和销毁,将堆栈空间释放到一个递归调用中

package com.company;

import java.util.Scanner;

public class Chef_prime_palindromes {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        long num = input.nextLong();
        isPalindrom(num + 1);
    }

    public static boolean isPrime(long num) {
        long i;
        for (i = 2; i < num; i++) {
            if (num % i == 0) {
                return false;
            }
        }
        return true;
    }

    private static void isPalindrom(long num) {
        for (; ; ) {
            if (isPalindrome(num)) {
                if (isPrime(num)) {
                    System.out.println(num);
                    System.exit(0);
                } else {
                    num++;
                }
            } else {
                num++;
            }
        }
    }

    public static boolean isPalindrome(long num) {
        String string = String.valueOf(num);
        return string.equals(new StringBuilder(string).reverse().toString());
    }
}

首先你应该意识到你的资源是有限的。即使您的实现是精确的,并且所有递归调用都是正确的,您仍然可能会得到错误。该错误表示JVM堆栈空间不足。尝试增加JVM堆栈的大小,有关详细信息,请参阅

另一件重要的事情是寻找素数和回文数的分布。您的代码通过针对回文属性测试每个num+1来运行。这是不正确的。只有当数字为素数时,才能测试回文。这将使计算更加容易,并减少递归调用。我已相应地编辑了您的代码,并获得了543212 1003001之后最接近的回文编号。这是:

    public static void main(String[] args) {

     Scanner input = new Scanner(System.in);
    long num = input.nextLong();
    //isPalindrome(num+1);
    nextPrimePalindrome(num+1);
    }

    public static void nextPrimePalindrome(long num)
    {
        boolean flag=true;
        while(flag)
        {
            if(isPrime(num))
                if(isPalindrome(num))
                {
                    System.out.println(num);
                    flag=false;
                }
              num++;      
        }
    }

public static boolean isPrime(long num){
    long i;
    for(i=2;i<num;i++){
        if(num%i == 0){
            return false;
        }
    }
    return true;
}

public static boolean isPalindrome(long num)
{
    String word=Long.toString(num);
    for(int i=0;i<word.length()/2;i++)
        if(word.charAt(i)!=word.charAt(word.length()-i-1))
            return false;
    return true;
}
}

首先你应该意识到你的资源是有限的。即使您的实现是精确的,并且所有递归调用都是正确的,您仍然可能会得到错误。该错误表示JVM堆栈空间不足。尝试增加JVM堆栈的大小,有关详细信息,请参阅

另一件重要的事情是寻找素数和回文数的分布。您的代码通过针对回文属性测试每个num+1来运行。这是不正确的。只有当数字为素数时,才能测试回文。这将使计算更加容易,并减少递归调用。我已相应地编辑了您的代码,并获得了543212 1003001之后最接近的回文编号。这是:

    public static void main(String[] args) {

     Scanner input = new Scanner(System.in);
    long num = input.nextLong();
    //isPalindrome(num+1);
    nextPrimePalindrome(num+1);
    }

    public static void nextPrimePalindrome(long num)
    {
        boolean flag=true;
        while(flag)
        {
            if(isPrime(num))
                if(isPalindrome(num))
                {
                    System.out.println(num);
                    flag=false;
                }
              num++;      
        }
    }

public static boolean isPrime(long num){
    long i;
    for(i=2;i<num;i++){
        if(num%i == 0){
            return false;
        }
    }
    return true;
}

public static boolean isPalindrome(long num)
{
    String word=Long.toString(num);
    for(int i=0;i<word.length()/2;i++)
        if(word.charAt(i)!=word.charAt(word.length()-i-1))
            return false;
    return true;
}
}

所有显示的现有解决方案都使用递归,并且在某个点上会出现StackOverflowException问题。 一个更好的并行化解决方案是将它变成一个循环

可能是这样的:

package nisarg;

import java.math.BigInteger;
import java.util.Scanner;
import java.util.concurrent.CopyOnWriteArrayList;


public class Chef_prime_palindromes {
    private static  final CopyOnWriteArrayList<BigInteger> PRIMESCACHE 
        = new CopyOnWriteArrayList<>();


    public static void main(String[] args) {
        try (Scanner input = new Scanner(System.in)) {
            BigInteger num = new BigInteger(input.nextLine());

            initPrimes(num);

            for (num = num.add(BigInteger.ONE);
                    !isPrimePalindrome(num); 
                    num = num.add(BigInteger.ONE)); 

            System.out.println(num.toString());
            }
    }

    private static void initPrimes(BigInteger upTo) {
        BigInteger i;
        for (i = new BigInteger("2"); i.compareTo(upTo) <= 0 ; i = i.add(BigInteger.ONE)) {
            isPrime(i);
        }
    }


    public static boolean isPrimePalindrome(BigInteger num) {
        return isPrime(num) && isPalindrome(num);
    }

    // could be optimized
    public static boolean isPrime(BigInteger num) {

        for (int idx = PRIMESCACHE.size() - 1; idx >= 0; --idx) {
            if (num.mod(PRIMESCACHE.get(idx)).compareTo(BigInteger.ZERO) == 0) {
                return false;
            }   
        }

        if (!PRIMESCACHE.contains(num)) {
            PRIMESCACHE.add(num);
        }
        return true;
    }

    public static boolean isPalindrome(BigInteger num) {
        String word = num.toString();
        int i;
        for (i = 0; i < word.length() / 2; i++) {
            if (word.charAt(i) != word.charAt(word.length() - i - 1)) {
                return false;
            }
        }
        return true;
    }
}

所有显示的现有解决方案都使用递归,并且在某个点上会出现StackOverflowException问题。 一个更好的并行化解决方案是将它变成一个循环

可能是这样的:

package nisarg;

import java.math.BigInteger;
import java.util.Scanner;
import java.util.concurrent.CopyOnWriteArrayList;


public class Chef_prime_palindromes {
    private static  final CopyOnWriteArrayList<BigInteger> PRIMESCACHE 
        = new CopyOnWriteArrayList<>();


    public static void main(String[] args) {
        try (Scanner input = new Scanner(System.in)) {
            BigInteger num = new BigInteger(input.nextLine());

            initPrimes(num);

            for (num = num.add(BigInteger.ONE);
                    !isPrimePalindrome(num); 
                    num = num.add(BigInteger.ONE)); 

            System.out.println(num.toString());
            }
    }

    private static void initPrimes(BigInteger upTo) {
        BigInteger i;
        for (i = new BigInteger("2"); i.compareTo(upTo) <= 0 ; i = i.add(BigInteger.ONE)) {
            isPrime(i);
        }
    }


    public static boolean isPrimePalindrome(BigInteger num) {
        return isPrime(num) && isPalindrome(num);
    }

    // could be optimized
    public static boolean isPrime(BigInteger num) {

        for (int idx = PRIMESCACHE.size() - 1; idx >= 0; --idx) {
            if (num.mod(PRIMESCACHE.get(idx)).compareTo(BigInteger.ZERO) == 0) {
                return false;
            }   
        }

        if (!PRIMESCACHE.contains(num)) {
            PRIMESCACHE.add(num);
        }
        return true;
    }

    public static boolean isPalindrome(BigInteger num) {
        String word = num.toString();
        int i;
        for (i = 0; i < word.length() / 2; i++) {
            if (word.charAt(i) != word.charAt(word.length() - i - 1)) {
                return false;
            }
        }
        return true;
    }
}

谢谢你,我明白你的意思。我忍不住又问了一个问题。这个堆栈的大小取决于机器还是语言,或者两者都有还是没有?它同时取决于机器和语言。关于不同JVM的java默认堆栈大小,请参阅本文。谢谢,我理解你的意思。我忍不住又问了一个问题。这个堆栈的大小取决于机器还是语言,或者两者都有还是没有?它同时取决于机器和语言。请参阅这篇文章,了解不同JVM的java默认堆栈大小。我没有递归:/抱歉,我没有仔细阅读-我的没有递归:/对不起,我读得不够仔细-