char digit = (char)(tmp.charAt(i) - '0');
In the ascii table, characters from '0' to '9' are contiguous. So, if you know that tmp.charAt(i) will return a character between 0 and 9, then subracting 0 will return the offset from zero, that is, the digit that that character represents.
char digit = (char)(tmp.charAt(i) - '0');
In the ascii table, characters from '0' to '9' are contiguous. So, if you know that tmp.charAt(i) will return a character between 0 and 9, then subracting 0 will return the offset from zero, that is, the digit that that character represents.
Using Math.pow is very expensive, you would be better off using Integer.parseInt.
You don't have to use Math.pow. If your numbers are always positive you can do
int result = 0;
for (int i = 0; i < tmp.length(); i++)
result = result * 10 + tmp.charAt(i) - '0';
All in all, that's a pretty good implementation in a number of key details.
Using the Character.isDigit() and Character.getNumericValue() methods are good to see.
The Math.* methods that handle the overflow conditions are good too.
I am not sure if you intended it, but you also correctly handle an obscure edge-case in 32-bit signed integer systems (not just Java), where Integer.MIN_VALUE is not the same as - Integer.MAX_VALUE ... and your code actually gets it right for an exact input of the text "-2147483648"
So, you have good details in your code.... and I can't see any broken edge-cases.
My only recommendation would be that a state-machine may make things simpler... with just one loop..... but the state-machine may be a bit messy too, although I think it works out better in the long run...
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;
}
Note that in a raw performance benchmark, I suspect your solution will be (slightly) faster, but I prefer readability over small incremental performance gains, unless performance is extremely critical.
There is a duplicate test for the '-' char. I'd rewrite
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;
I would also add support for hexadecimal numbers.