算法涉及较少,主要是考虑细节
- 字符串为null或空””
- -,+判断
- illegal的字符(字符串中包含非数字)
- 字符串长度问题,只有’+’或’-‘
- 溢出问题
1 | package StringToInteger; |
一般判断溢出会这样判断 digit > INT_MAX - result*10 (先不考虑正负问题),但是这段代码是有问题的。
INT_MAX = 2147483647, 如果输入的字符串是2147483657,那么执行到最后一位时,会有 result*10 = 2147483650 > INT_MAX,此时已经溢出,所以答案必然出错。
对于正数来说,溢出有两种可能:
一种是诸如 2147483650,即 result > MAX/10 的;
一种是诸如 2147483649,即 result == MAX/10 && digit > MAX%10 的。
解决办法
- 先用result与INT_MAX/10比较,如果result>INT_MAX/10,那么必然溢出
- 如果result=INT_MAX/10,比较此时的digit位,如果digit>INT_MAX%10,那么也必然溢出
INT_MAX = 2147483647 而 INT_MIN = -2147483648,两者绝对值不相等。因此,正负数溢出的条件不一样,所以代码中用了两个条件来判断溢出情况。
JDK 中 parseInt
1 | /* |
JDK 将所有的整数先当做负数来处理了,为什么呢?
我们知道有符号 int 的上下限是-2147483648 ~ 2147483647,可见负数表达的范围比正数多一个,这样就好理解为什么在开头要把 limit 全部表达为负数(下限)。这样的操作减少了后续的判断,可以一步到位,相当于二者选择取其大一样,大的包含了小的,不用像我的代码一样正负数情况都判断一次。同理,那么 multmin 也都是负数了,而且可以认为是只和进制参数 radix 有关系。在这里 multmin 就是-INT_MAX/10,当负数时就是INT_MIN/10。所以与上文类似,第一个条件就是若-result < -INT_MAX/10则是溢出。不满足第一个条件的情况下,result10肯定不会溢出了。所以第二个条件判断若 - result10 < -INT_MAX + digit,则是溢出。
比如对于最大的负数来说,当扫描到最后一位时,result = -214748364,multmin=-214748364
第一个条件result < multmin不满足, 执行result *= radix之后,result = -2147483640
第二个条件result < limit + digit,即 -2147483640<-2147483648+8 也不满足条件。
所以正常输出。