Java String 转整形

最近看剑指 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

 

posted @ 2019-03-14 17:47  Ainsliaea  阅读(3609)  评论(0编辑  收藏  举报