Java的字符串轉int算法


面T家,被要求實現一個字符串轉整型數的算法,當時手寫有點遺漏,現在回頭來看看jdk的實現。
常用的是Integer.valueOf方法來實現轉換:

1     public static Integer valueOf(String s) throws NumberFormatException {
2         return Integer.valueOf(parseInt(s, 10));
3     }

默認會調用parseInt方法進行轉換,參數中的10說明是按照10進制進行轉換的。

 

看看parseInt方法:

 1     public static int parseInt(String s, int radix)
 2                 throws NumberFormatException
 3     {
 4 
 5         if (s == null) {
 6             throw new NumberFormatException("null");
 7         }
 8 
 9         if (radix < Character.MIN_RADIX) {
10             throw new NumberFormatException("radix " + radix +
11                                             " less than Character.MIN_RADIX");
12         }
13 
14         if (radix > Character.MAX_RADIX) {
15             throw new NumberFormatException("radix " + radix +
16                                             " greater than Character.MAX_RADIX");
17         }
18 
19         int result = 0;
20         boolean negative = false;
21         int i = 0, len = s.length();
22         int limit = -Integer.MAX_VALUE;
23         int multmin;
24         int digit;
25 
26         if (len > 0) {
27             char firstChar = s.charAt(0);
28             if (firstChar < '0') { // Possible leading "+" or "-"
29                 if (firstChar == '-') {
30                     negative = true;
31                     limit = Integer.MIN_VALUE;
32                 } else if (firstChar != '+')
33                     throw NumberFormatException.forInputString(s);
34 
35                 if (len == 1) // Cannot have lone "+" or "-"
36                     throw NumberFormatException.forInputString(s);
37                 i++;
38             }
39             multmin = limit / radix;
40             while (i < len) {
41                 // Accumulating negatively avoids surprises near MAX_VALUE
42                 digit = Character.digit(s.charAt(i++),radix);
43                 if (digit < 0) {
44                     throw NumberFormatException.forInputString(s);
45                 }
46                 if (result < multmin) {
47                     throw NumberFormatException.forInputString(s);
48                 }
49                 result *= radix;
50                 if (result < limit + digit) {
51                     throw NumberFormatException.forInputString(s);
52                 }
53                 result -= digit;
54             }
55         } else {
56             throw NumberFormatException.forInputString(s);
57         }
58         return negative ? result : -result;
59     }

首先看到5-17行是邊界檢查:

  • 如果字符串s是空指針,直接拋異常
  • 如果進制小於最小進制(常量定義為2),拋異常
  • 如果進制大於最大進制(常量定義為36),拋異常

接下來19-24行是局部變量定義,這里需要注意一個就是limit被賦值為int表示的最大正整型數的負值,也就是-2147483647

再往下看到26-38行,如果字符串s長度大於0,那么首先看看首字符

  • 如果首字符小於字符0,那么可能是符號 + 或者 - ,要區別對待了
    • 如果是符號 - ,說明是個負數,將布爾值變量negative設置為true,並將limit設置為int型整數的下限值,也就是-2147483648
    • 如果首字符不是符號 +,說明首字符既不是數字也不是符號,則拋出異常
  • 再接下來看,如果首字符是符號 - 或者 +,但是字符串長度只有1,也就是說只有一個符號,那么也是不能夠轉為整型數的,直接拋異常

 

再往下39-54行

局部變量mulmin賦值為limit除以當前轉換的進制。接下來是一個循環,i代表處理的字符串的位數。
用局部變量digit記錄字符串s第i位數字的相應進制的值,接下來又是一些判斷了:

  • 如果digit小於0,拋異常
  • 如果result變量小於mulmin,拋異常,這里可以限制之后的乘法操作肯定不溢出;之后result變量乘以當前轉換進制。(如果result小於mulmin也就是limit/radix了,那么后面的乘以radix肯定就會小於limit,對於負數就超過了Integer的范圍,對於正數也是超過了Integer.MAX_VALUE
  • 如果此時result小於limit加上digit,拋異常,這里可以限制之后的減法操作不會溢出;之后result變量減去digit的值。(這個拋異常和上一條原因類似,也是為了防止溢出)

 

最后58行,如果negative為true,則直接返回result,否則返回負的result。

這個有點意思,如果是負數直接輸出,如果是正數反而是用負數取負,負負得正來表示的
個人覺得應該是整型數從絕對值來看,負數的范圍比正數大1,如果用result += digit這樣來進行計算的話,那么最小值-2147483648會無法被正確轉換。因為2147483640+8會得到-2147483648,然后再取負數的話,就變成0了。但是使用-=來計算,因為負數的范圍更大,因此正數是可以全部表示出來的,而且不管是+0還是-0都不會有問題,都可以得到數值0


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM