1. 程式人生 > >Java String 轉整形

Java String 轉整形

情況 view etc tar for character inpu tps ati

最近看劍指 Offer,最後有一道字符串轉整形的題,雖然題本身不難,但是需要考慮很多特殊情況,包括參數為空字符串、null 以及溢出等。

好奇看了一下 Java 源碼中 Integer 類的 parseInt() 方法的實現(valueOf() 方法調用了parseInt() 方法),發現這個實現對於溢出的處理很巧妙,故在此處記錄一下。

之前自己實現字符串轉整形的方法時,用 long 來表示最後轉換完的結果,然後再強轉成 int 型,這樣可以方便的處理溢出的情況。

技術分享圖片
// 部分參考了 Integer.parseInt() 的實現
static int strToInt(String str){
    
if (str == null || str.length() == 0) throw new NumberFormatException(str); long res = 0; boolean negative = false; int len = str.length(); int i = 0; char firstChar = str.charAt(0); if (firstChar < ‘0‘){ if (firstChar == ‘-‘){ negative = true
; }else if (firstChar != ‘+‘){ throw new NumberFormatException(str); } if (len == 1){ throw new NumberFormatException(str); } i++; } while(i < len){ char ch = str.charAt(i); if (ch < ‘0‘ || ch > ‘9‘){
throw new NumberFormatException(str); } int digit = str.charAt(i++) - ‘0‘; res = res * 10 + digit; if (negative == false && res > Integer.MAX_VALUE){ throw new NumberFormatException(str); } if (negative == true && res - 1 > Integer.MAX_VALUE){ throw new NumberFormatException(str); } } return negative ? -(int)res : (int)res; }
View Code

然後看到了 Integer.parseInt() 的實現,每次進行乘操作和加(這裏是減)操作之前,都會先判斷一下最終結果的大小,如果有可能超出 int 的範圍,就不會執行乘或減的運算。

技術分享圖片
public static int parseInt(String s, int radix) throws NumberFormatException{
    // 省略異常情況的判斷。。。

    int result = 0;
    boolean negative = false;
    int i = 0, len = s.length();
    int limit = -Integer.MAX_VALUE;
    int multmin;
    int digit;

    if (len > 0) {
        char firstChar = s.charAt(0);
        if (firstChar < ‘0‘) { // Possible leading "+" or "-"
            if (firstChar == ‘-‘) {
                negative = true;
                limit = Integer.MIN_VALUE;
            } else if (firstChar != ‘+‘)
                throw NumberFormatException.forInputString(s);

            if (len == 1) // Cannot have lone "+" or "-"
                throw NumberFormatException.forInputString(s);
            i++;
        }
        multmin = limit / radix;
        while (i < len) {
            // Accumulating negatively avoids surprises near MAX_VALUE
            digit = Character.digit(s.charAt(i++),radix);
            if (digit < 0) {
                throw NumberFormatException.forInputString(s);
            }
            if (result < multmin) { // 乘進位之前判斷
                throw NumberFormatException.forInputString(s);
            }
            result *= radix;
            if (result < limit + digit) { //加上個位之前再次判斷
                throw NumberFormatException.forInputString(s);
            }
            result -= digit;
        }
    } else {
        throw NumberFormatException.forInputString(s);
    }
    return negative ? result : -result;
}
View Code

LeetCode 上有一道轉整形的題,允許更多的輸入情況。順便做了一下,代碼如下(14 ms,38.6 M):

技術分享圖片
public int myAtoi(String str) {
  if (str == null)
       return 0;

   long res = 0;
   boolean negative = false;
   int i = 0;

   str = str.trim();

   if (str.length() == 0){
       return 0;
   }

   int len = str.length();

   char firstChar = str.charAt(0);

       if (firstChar == ‘-‘){
           negative = true;
           i++;
       }else if (firstChar == ‘+‘){
           i++;
       }

   while(i < len){
       char ch = str.charAt(i);
       if (ch < ‘0‘ || ch > ‘9‘){
           return negative ? -(int)res : (int)res;
       }

       int digit = str.charAt(i++) - ‘0‘;
       res = res * 10 + digit;

       if (negative == false && res > Integer.MAX_VALUE){
           return Integer.MAX_VALUE;
       }
       if (negative == true && res - 1 > Integer.MAX_VALUE){
           return Integer.MIN_VALUE;
       }
   }

   return negative ? -(int)res : (int)res;
}
View Code

Java String 轉整形