Implementando String en int (atoi) en Java

La función primero descarta tantos espacios en blanco como sea necesario hasta se encuentra el primer carácter que no es un espacio en blanco. Luego, a partir de este carácter, toma un signo más o menos inicial opcional seguido de tantos dígitos numéricos como sea posible y los interpreta como un valor numérico.

La cadena puede contener caracteres adicionales después de los que forman el número entero, que se ignoran y no tienen ningún efecto en el comportamiento de esta función.

Si la primera secuencia de caracteres que no son espacios en blanco en str no es un número entero válido, o si no existe tal secuencia porque str está vacío o contiene sólo caracteres de espacio en blanco, no se realiza ninguna conversión.

Si no se pudo realizar una conversión válida, se devuelve un valor cero. Si el valor correcto está fuera del rango de valores representables, se devuelve INT_MAX (2147483647) o INT_MIN (-2147483648).

No estoy seguro sobre mis comprobaciones contra el desbordamiento de enteros, pero aquí está mi implementación:

public int myAtoi(String str) { int i = 0; while (i < str.length() && Character.isWhitespace(str.charAt(i))) { ++i; } if (i == str.length()) { return 0; } boolean isNegative = false; if (str.charAt(i) == "+" || str.charAt(i) == "-") { isNegative = str.charAt(i) == "-"; ++i; } int result = 0; while (i < str.length() && Character.isDigit(str.charAt(i))) { try { result = Math.multiplyExact(result, 10); result = Math.addExact(result, Character.getNumericValue(str.charAt(i))); } catch (ArithmeticException e) { return isNegative ? Integer.MIN_VALUE : Integer.MAX_VALUE; } ++i; } if (isNegative) { result = -result; } return result; } 

Respuesta

En general, esa es una implementación bastante buena en una serie de detalles clave.

Usando Character.isDigit() y Character.getNumericValue().

Los métodos Math.* que manejan las condiciones de desbordamiento también son buenos.

No estoy seguro si lo deseaba, pero también maneja correctamente un caso de borde oscuro en sistemas enteros de 32 bits con signo (no solo Java), donde Integer.MIN_VALUE no es lo mismo que - Integer.MAX_VALUE … y su código realmente lo hace bien para una entrada exacta del texto «-2147483648»

Entonces, tiene buenos detalles en su código … y No puedo ver ningún caso de borde roto.

Mi única recomendación sería que una máquina de estado puede simplificar las cosas … con un solo bucle ….. pero la máquina de estado también puede ser un poco desordenada, aunque creo que funciona mejor en a largo plazo …

public static int rlAtoi(String str) { boolean started = false; boolean negative = false; int result = 0; try { for (char c : str.toCharArray()) { if (!started && Character.isWhitespace(c)) { // great, ignore it. } else if (!started && (c == "+" || c == "-")) { // great, a sign negative = c == "-"; started = true; } else if (Character.isDigit(c)) { result = Math.multiplyExact(result, 10); result = Math.addExact(result, Character.getNumericValue(c)); started = true; } else { // done.... break; } } } catch (ArithmeticException e) { return negative ? Integer.MIN_VALUE : Integer.MAX_VALUE; } return negative ? -result : result; } 

Tenga en cuenta que en un punto de referencia de rendimiento sin procesar, sospecho que su solución será (un poco) más rápida, pero prefiero la legibilidad a la pequeña ganancias de rendimiento incrementales, a menos que el rendimiento sea extremadamente crítico.

Comentarios

  • +1 para la máquina de estado, ya que esto es mucho más fácil, casi siempre más rápido y mucho más fácil de depurar / extender.

Respuesta

Hay una prueba duplicada para el carácter «-«. «Reescribiría

boolean isNegative = false; if (str.charAt(i) == "+" || str.charAt(i) == "-") { isNegative = str.charAt(i) == "-"; ++i; } 

como

boolean isNegative = false; if (str.charAt(i) == "-") { isNegative= true; ++i; } else if (str.charAt(i) == "+") ++i; 

También agregaría soporte para hexadecimal números.

Comentarios

  • Un bloque switch también funcionaría bien aquí.
  • Ah, eso ' es cierto. Un switch con fall-through probablemente tendría la menor duplicación.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *