String implementeren naar int (atoi) in Java

De functie verwijdert eerst zoveel spaties als nodig is tot het eerste niet-witruimte-teken wordt gevonden. Beginnend met dit teken, neemt een optioneel initieel plus- of minteken gevolgd door zoveel mogelijk numerieke cijfers, en interpreteert deze als een numerieke waarde.

De string kan extra tekens bevatten na de tekens die de integraal getal, die worden genegeerd en geen effect hebben op het gedrag van deze functie.

Als de eerste reeks niet-witruimtetekens in str geen geldig geheel getal is, of als een dergelijke reeks niet bestaat omdat ofwel str is leeg of bevat alleen spaties, er wordt geen conversie uitgevoerd.

Als er geen geldige conversie kan worden uitgevoerd, wordt een nulwaarde geretourneerd. Als de juiste waarde buiten het bereik van representeerbare waarden valt, wordt INT_MAX (2147483647) of INT_MIN (-2147483648) geretourneerd.

Ik weet het niet zeker over mijn controles op integer-overflow, maar hier is mijn implementatie:

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

Al met al “een redelijk goede implementatie in een aantal belangrijke details.

Met behulp van de Character.isDigit() en Character.getNumericValue() methoden zijn goed om te zien.

De Math.* methoden die omgaan met de overflow condities zijn ook goed.

Ik weet het niet zeker als je het bedoeld had, maar je behandelt ook correct een obscure edge-case in 32-bits ondertekende integer-systemen (niet alleen Java), waar Integer.MIN_VALUE niet hetzelfde is als - Integer.MAX_VALUE … en je code krijgt het echt goed voor een exacte invoer van de tekst “-2147483648”

Dus je hebt goede details in je code … en Ik zie geen gebroken randgevallen.

Mijn enige aanbeveling zou zijn dat een state-machine dingen eenvoudiger kan maken … met slechts één lus ….. maar de state-machine kan ook een beetje rommelig zijn, hoewel ik denk dat het beter werkt in de lange termijn …

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

Merk op dat in een onbewerkte prestatiebenchmark, ik vermoed dat uw oplossing (iets) sneller zal zijn, maar ik geef de voorkeur aan leesbaarheid boven kleine incrementele prestatieverbeteringen, tenzij de prestaties extreem kritisch zijn.

Reacties

  • +1 voor state machine, aangezien dit veel gemakkelijker, bijna altijd sneller en veel gemakkelijker te debuggen / uitbreiden.

Antwoord

Er is een dubbele test voor het “-” teken. Ik zou “herschrijven

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

as

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

Ik zou ook ondersteuning voor hexadecimale cijfers.

Reacties

  • Een switch blok zou hier ook goed werken.
  • Ah, dat ' is waar. Een switch met fall-through zou waarschijnlijk de minste duplicatie hebben.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *