java程序中的stackoverflowerr
我试图解决一个问题,它要求找到最小的素数回文,它位于给定的数字之后,这意味着如果输入是24,那么输出将是101,因为它是24之后的最小数,同时也是素数和回文 现在,我的代码可以完美地处理小值,但当我插入543212之类的东西作为输入时,第20行出现了StackOverflower错误,第24行出现了StackOverflower错误的多个实例。这是我的密码: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
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默认堆栈大小。我没有递归:/抱歉,我没有仔细阅读-我的没有递归:/对不起,我读得不够仔细-