Funcția renunță mai întâi la cât mai multe caractere de spațiu alb până este necesar se găsește primul caracter non-spațiu alb. Apoi, pornind de la acest caracter, ia un semn inițial plus sau minus opțional urmat de cât mai multe cifre numerice posibil și le interpretează ca o valoare numerică.
Șirul poate conține caractere suplimentare după cele care formează număr integral, care sunt ignorate și nu au niciun efect asupra comportamentului acestei funcții.
Dacă prima secvență de caractere care nu sunt spații albe în str nu este un număr integral valid sau dacă nu există o astfel de secvență, deoarece fie str este gol sau conține doar caractere în spațiu alb, nu se efectuează nicio conversie.
Dacă nu s-a putut efectua o conversie validă, se returnează o valoare zero. Dacă valoarea corectă este în afara valorii reprezentabile, INT_MAX (2147483647) sau INT_MIN (-2147483648) este returnat.
Nu sunt sigur despre verificările mele împotriva depășirii de numere întregi, dar iată implementarea mea:
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; }
Răspuns
Una peste alta, „este o implementare destul de bună într-o serie de detalii cheie.
Folosind Character.isDigit()
și Character.getNumericValue()
metodele sunt bune de văzut.
De asemenea, metodele Math.*
care gestionează condițiile de depășire sunt bune.
Nu sunt sigur dacă ați intenționat-o, dar gestionați corect o margine obscură în sistemele întregi semnate pe 32 de biți (nu doar Java), unde Integer.MIN_VALUE
nu este același lucru cu - Integer.MAX_VALUE
… și codul dvs. este de fapt corect pentru o introducere exactă a textului „-2147483648”
Deci, aveți detalii bune în codul dvs. …. și Nu pot să văd niciun caz de margine rupt.
Singura mea recomandare ar fi că o mașină de stat poate face lucrurile mai simple … cu o singură buclă ….. dar mașina de stare poate fi și ea un pic dezordonată, deși cred că funcționează mai bine în pe termen lung …
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; }
Rețineți că într-un benchmark de performanță brut, bănuiesc că soluția dvs. va fi (ușor) mai rapidă, dar prefer lizibilitatea în locul celor mici câștiguri de performanță incrementale, cu excepția cazului în care performanța este extrem de critică.
Comentarii
- +1 pentru mașina de stat, deoarece acest lucru este mult mai ușor, aproape întotdeauna mai rapid și mult mai ușor de depanat / extins.
Răspuns
Există un test duplicat pentru caracterul „-„. „Aș rescrie
boolean isNegative = false; if (str.charAt(i) == "+" || str.charAt(i) == "-") { isNegative = str.charAt(i) == "-"; ++i; }
ca
boolean isNegative = false; if (str.charAt(i) == "-") { isNegative= true; ++i; } else if (str.charAt(i) == "+") ++i;
Aș adăuga și suport pentru hexadecimal numere.
Comentarii
- Un bloc
switch
ar funcționa bine și aici. - Ah, ' este adevărat. Un
switch
cu rezolvare probabil ar avea cea mai mică dublare.