"123"
这样的字符串转成int
, 是一个常见功能.昨天我实现了几个残废版本,只支持10进制,加上代码特别丑,难受死了。没看到的可以戳下这里《剑指offer第67题解析》。
今天, 我们来填个坑,看一下java
里的Integer.parseInt
函数是怎么实现的.
字符串转整数
因为昨天写过了, 所以今天就直接带着问题去看.主要关心下面两点.
-
怎么处理负数比正数多一个的问题 -
怎么检测是否溢出
正负数表示范围问题
昨天写起来最烦心的部分, 是Integer.MAX_VALUE
绝对值比Integer.MIN_VALUE
小1.如果使用上一轮结果*进制+当前数字
,在遇到这个边界值时候就会出问题.
首先,就要去看Integer.parseInt
怎么解决这个问题.
打开源码以后, 看到这我笑了.实属会玩儿, 太有意思了.
//略有删节
while (i < len) {
int digit = Character.digit(s.charAt(i++), radix);
result *= radix;
result -= digit;
}
这里的写法很偷鸡, 不是说正数比负数少么? 直接算负数不就好了.
怎么检测数字溢出?
32位有符号整数,上界是有限的,2147483647
,下界-2147483648.
-
如果前面已经算到了 214748365
,在进行214748365* 10
的过程中,直接就溢出了. -
如果前面算到的是 214748364
, 又读到了一个8
. -
在正数时候,读到8,就溢出了 -
负数时候,读到7就溢出了
这东西写起来还是贼烦的. 昨天为了偷鸡, 我把整数用long
表示绕过去了,很好奇java
怎么解决.
结果他们类似是这么写的.
int limit =negative?Integer.MIN_VALUE:-Integer.MAX_VALUE:;
int multmin = limit / radix;
if (result < multmin || result < limit + digit ) {
throw NumberFormatException.forInputString(s, radix);
}
以10进制为例:
-
这里计算出了一个翻10倍后会溢出的上界
214748364
,翻前直接进行检测 -
剩下第二种情况的检测比较有趣,
result < limit + digit
,因为limit
几乎是最小值,加上一个数字是不会溢出的.而如果反转变成result - digit < limit
则会.这里巧妙绕过去了.喵喵喵,妙得很!
学以致用
用刚刚学到的技巧,改进版解法重新解剑指offer67题,代码如下。
int start = 0, end = str.length();
for (; start < end; start++) {
if (!Character.isSpaceChar(str.charAt(start))) {
break;
}
}
if (end == start) return 0;
boolean negative = false;
int limit = -Integer.MAX_VALUE;
char first = str.charAt(start++);
if (first == '-') {
negative = true;
limit = Integer.MIN_VALUE;
} else if (first != '+') {
start--;
}
int RADIX = 10;
int multimin = limit / RADIX;
int sum = 0;
for (; start < end; start++) {
int digit = str.charAt(start)-'0';
if (digit < 0||digit>9) break;
if (sum < multimin) {
sum = limit;
break;
}
sum *= RADIX;
if (sum < limit + digit) {
sum = limit;
break;
}
sum -= digit;
}
return negative ? sum : -sum;
后话
今天是填坑, 所以, 就到这里.
用负数来做累计这部分, 在我看来简直是神来之笔, 省掉了很多不必要的麻烦.还有就是为了躲开溢出, 最后一步不等式移项转成加法来判断式子大小关系,也很有趣.
题图来自萌娘百科, 特里休·乌纳,一个头上写满加减乘除的替身使者.
https://zh.moegirl.org.cn/特里休·乌纳
原文始发于微信公众号(K字的研究):Java数字解析, Integer.parseInt源码写的妙啊
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/29711.html