Implementazione della stringa in int (atoi) in Java

La funzione innanzitutto elimina tutti i caratteri di spazio necessari finché viene trovato il primo carattere diverso da spazi. Quindi, a partire da questo carattere, prende un segno più o meno iniziale opzionale seguito da quante più cifre numeriche possibile e le interpreta come un valore numerico.

La stringa può contenere caratteri aggiuntivi dopo quelli che formano il numero intero, che vengono ignorati e non hanno alcun effetto sul comportamento di questa funzione.

Se la prima sequenza di caratteri diversi da spazi in str non è un numero intero valido, o se tale sequenza non esiste perché str è vuoto o contiene solo spazi vuoti, non viene eseguita alcuna conversione.

Se non è possibile eseguire una conversione valida, viene restituito un valore zero. Se il valore corretto non rientra nellintervallo di valori rappresentabili, viene restituito INT_MAX (2147483647) o INT_MIN (-2147483648).

Non sono sicuro sui miei controlli rispetto a integer overflow, ma ecco la mia implementazione:

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; } 

Answer

Tutto sommato, si tratta di “unimplementazione piuttosto buona in una serie di dettagli chiave.

Usare Character.isDigit() e Character.getNumericValue() sono belli da vedere.

Anche i metodi Math.* che gestiscono le condizioni di overflow sono buoni.

Non sono sicuro se lo intendevi, ma gestisci correttamente anche un oscuro caso limite nei sistemi con interi con segno a 32 bit (non solo Java), dove Integer.MIN_VALUE non è la stessa cosa di - Integer.MAX_VALUE … e il tuo codice effettivamente lo fa correttamente per un input esatto del testo “-2147483648”

Quindi, hai buoni dettagli nel tuo codice …. e Non riesco a vedere nessun caso limite rotto.

La mia unica raccomandazione sarebbe che una macchina a stati possa rendere le cose più semplici … con un solo ciclo ….. ma anche la macchina a stati potrebbe essere un po disordinata, anche se penso che funzioni meglio in a lungo termine …

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; } 

Nota che in un benchmark delle prestazioni non elaborate, sospetto che la tua soluzione sarà (leggermente) più veloce, ma preferisco la leggibilità rispetto al piccolo guadagni incrementali delle prestazioni, a meno che le prestazioni non siano estremamente critiche.

Commenti

  • +1 per la macchina a stati, poiché è molto più semplice, quasi sempre più veloce e molto più facile da eseguire il debug / estendere.

Risposta

Esiste un test duplicato per il carattere “-“. Ho “d riscritto

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

come

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

Aggiungerei anche il supporto per esadecimale numeri.

Commenti

  • Un switch blocco funzionerebbe bene anche qui.
  • Ah, questo ' è vero. Un switch con fall-through avrebbe probabilmente la minima duplicazione.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *