Método recursivo para converter string em número

Pessoal estou com um problema com um programa que faz uma recursão; o intuito do programa e pegar uma String de numeros, converter em inteiro e concatenar. o problema é que quando chega em uma determinada quatidade de numeros da uma “java.base/java.lang.NumberFormatException” ou as vezes nao retorna o “0” como int;

public class Recur {

public static void main(String[] args) {
	System.out.print(conv("56286788646"));
}
	
private static int conv(String i) {
	String[] e = i.split("");

	if(e.length == 1) {
		return Integer.parseInt(e[0].toString());
	}
	else {
		return Integer.parseInt(e[0].toString() + conv(i.substring(1)));
	}
}

}

Aqui não faz muito sentido, porque você converte o primeiro dígito para string, e depois concatena com o resultado da conversão do restante da string. Mas quando você soma uma string com um número, o resultado é uma string.

Ou seja, no final você terá a mesma string que foi passada inicialmente. Toda essa recursão pode ser trocada simplesmente por Integer.parseInt(i), já que o resultado final será uma string com o conteúdo igual a i.

Também tem outro problema: o valor máximo de um int é 2.147.483.647 (pouco mais de 2 bilhões), mas você passou uma string que corresponde a um número bem maior, então no fim vai dar erro na conversão, já que parseInt lança uma exceção se o valor não estiver dentro dos limites de um int.


Mas vamos por partes.

Primeiro, vale dizer que recursão nem é a melhor solução para o seu problema (afinal, Integer.parseInt(i) já resolveria). Existem casos de uso legítimos para recursão (quando vai lidar com estruturas que são naturalmente recursivas, como árvores, por exemplo), mas tem casos como esse, em que claramente não é a melhor opção (cada caso é um caso), então questiono se essa é a melhor forma de aprender recursão.

Dito isso, se quer converter a string para inteiro, uma ideia é:

  • se só tem um caractere, converta-o para número
  • se tem mais caracteres, converta o primeiro para número, multiplique por 10tamanho da string - 1 e some com a conversão do restante

Por exemplo, se a string for “456”, o algoritmo seria somar 4 * 102 + 5 * 10 + 6:

  • o primeiro dígito (“4”) deve ser multiplicado por 102 (10 elevado ao tamanho da string menos 1), já que ele equivale às centenas
  • depois fazemos a chamada recursiva passando o restante da string (“56”)
    • agora o primeiro dígito é “5”, e o tamanho da string é 2, portanto fazemos 5 * 101
    • e fazemos a chamada recursiva passando o restante da string (“6”)
      • como agora o tamanho da string é 1, convertemos ela para número e retornamos

Portanto fica assim:

private static int conv(String s) {
    if (s.length() == 1) {
        return Integer.parseInt(s);
    }
    // 10 elevado a (tamanho da string menos 1)
    int p = (int) Math.pow(10, s.length() - 1);
    // primeiro dígito vezes 10 elevado a (tamanho da string menos 1), somado com a conversão do restante da string
    return Integer.parseInt(s.substring(0, 1)) * p + conv(s.substring(1));
}

Mas claro que ainda tem o problema de não funcionar com valores maiores que 2.147.483.647. Se quer isso, pode trocar para long (lembrando que ainda sim tem um valor máximo, que é 9.223.372.036.854.775.807 - cerca de 9 quintilhões):

private static long conv(String s) {
    if (s.length() == 1) {
        return Long.parseLong(s);
    }
    long p = (long) Math.pow(10, s.length() - 1);
    return Long.parseLong(s.substring(0, 1)) * p + conv(s.substring(1));
}

Assim funciona para strings como "56286788646".