Implementace String to int (atoi) v Javě

Funkce nejprve zahodí tolik mezer, kolik je potřeba, dokud je nalezen první znak bez mezer. Poté, počínaje tímto znakem, vezme volitelný počáteční znak plus nebo minus následovaný co největším počtem číslic a interpretuje je jako číselnou hodnotu.

Řetězec může obsahovat další znaky za těmi, které tvoří integrální číslo, které jsou ignorovány a nemají žádný vliv na chování této funkce.

Pokud první posloupnost znaků, které nejsou mezery v str, není platné celé číslo, nebo pokud taková posloupnost neexistuje, protože buď str je prázdný nebo obsahuje pouze prázdné znaky, neprovádí se žádný převod.

Pokud nelze provést platný převod, je vrácena nulová hodnota. Pokud je správná hodnota mimo rozsah reprezentovatelných hodnot, je vrácena INT_MAX (2147483647) nebo INT_MIN (-2147483648).

Nejsem si jistý o mých kontrolách proti přetečení celého čísla, ale tady je moje implementace:

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

Odpovědět

Celkově vzato, že „je docela dobrá implementace v řadě klíčových detailů.

Pomocí Character.isDigit() a Character.getNumericValue() jsou dobře vidět.

Metody Math.*, které zpracovávají podmínky přetečení, jsou také dobré.

Nejsem si jistý pokud jste to zamýšleli, ale také správně zacházíte s obskurní hranou v 32bitových celočíselných systémech se znaménkem (nejen v Javě), kde Integer.MIN_VALUE není totéž jako - Integer.MAX_VALUE … a váš kód to vlastně udělá přesně pro přesné zadání textu „-2147483648“

Takže ve svém kódu máte dobré podrobnosti …. a Nevidím žádné případy zlomené hrany.

Moje jediné doporučení by bylo, že stavový stroj může dělat věci jednodušší … pouze s jednou smyčkou ….. ale stavový stroj může být také trochu chaotický, i když si myslím, že to funguje lépe v dlouhodobý běh …

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

Všimněte si, že v surovém měřítku výkonu mám podezření, že vaše řešení bude (mírně) rychlejší, ale dávám přednost čitelnosti před malými přírůstkové zvýšení výkonu, pokud není výkon extrémně kritický.

Komentáře

  • +1 pro stavový stroj, protože je to mnohem jednodušší, téměř vždy rychlejší a mnohem jednodušší ladění / rozšíření.

Odpověď

U znaku „-“ existuje duplicitní test. Přepíšu

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

jako

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

Také bych přidal podporu pro hexadecimální čísla.

Komentáře

  • Blok switch by zde také dobře fungoval.
  • Ah, to ' s pravdou. switch s přepadem by pravděpodobně mělo nejmenší duplikaci.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *