Funktionen förstör så många blankstegstecken som behövs tills den första icke-blankstegstecknet hittas. Från och med det här tecknet tar sedan ett valfritt initialt plus- eller minustecken följt av så många numeriska siffror som möjligt och tolkar dem som ett numeriskt värde.
Strängen kan innehålla ytterligare tecken efter de som bildar integralt nummer, som ignoreras och inte har någon inverkan på funktionen för denna funktion.
Om den första sekvensen av icke-blankstegstecken i str inte är ett giltigt integralt nummer, eller om ingen sådan sekvens existerar eftersom antingen str är tom eller den innehåller endast blankstegstecken, ingen konvertering utförs.
Om ingen giltig konvertering kunde utföras returneras ett nollvärde. Om det korrekta värdet ligger utanför intervallet för representerbara värden returneras INT_MAX (2147483647) eller INT_MIN (-2147483648).
Jag är inte säker om mina kontroller mot heltalsflöde, men här är min implementering:
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; }
Svar
Sammantaget är det ”en ganska bra implementering i ett antal viktiga detaljer.
Med Character.isDigit()
och Character.getNumericValue()
-metoder är bra att se.
Math.*
-metoderna som hanterar överflödsförhållandena är också bra.
Jag är inte säker om du tänkte det, men du hanterar också korrekt ett obskärt kantfall i 32-bitars signerade heltalssystem (inte bara Java), där Integer.MIN_VALUE
inte är samma som - Integer.MAX_VALUE
… och din kod får faktiskt rätt för en exakt inmatning av texten ”-2147483648”
Så, du har bra detaljer i din kod …. och Jag kan inte se några trasiga kanter.
Min enda rekommendation skulle vara att en statsmaskin kan göra saker enklare … med bara en slinga ….. men tillståndsmaskinen kan också vara lite rörigt, även om jag tycker att det fungerar bättre i i det långa loppet …
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; }
Observera att i en rå prestandamätpunkt tror jag att din lösning kommer att vara (något) snabbare, men jag föredrar läsbarhet framför små inkrementella prestationsvinster, såvida inte prestanda är extremt kritisk.
Kommentarer
- +1 för tillståndsmaskin, eftersom det här är mycket lättare, nästan alltid snabbare och mycket lättare att felsöka / förlänga.
Svar
Det finns ett dubblettest för ”-” -tecknet. Jag skulle skriva om
boolean isNegative = false; if (str.charAt(i) == "+" || str.charAt(i) == "-") { isNegative = str.charAt(i) == "-"; ++i; }
som
boolean isNegative = false; if (str.charAt(i) == "-") { isNegative= true; ++i; } else if (str.charAt(i) == "+") ++i;
Jag skulle också lägga till stöd för hexadecimal siffror.
Kommentarer
- Ett
switch
block skulle också fungera bra här. - Ah, att ' är sant. En
switch
med genomslag skulle antagligen ha minst dubblering.