Java数字解析, Integer.parseInt源码写的妙啊

"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>9break;
    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/特里休·乌纳




Java数字解析, Integer.parseInt源码写的妙啊

原文始发于微信公众号(K字的研究):Java数字解析, Integer.parseInt源码写的妙啊

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/24737.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!