Java判斷整數溢出


開題報告第一版寫完發給老師了,熬了兩周終於搞出來了,等着被懟了之后再改吧。晚上選了Leetcode一道簡單的題,整數反轉,就是將一個int類型的數反轉。原本確實很簡單,最后出現個問題有意思——整數溢出。

溢出

題目給出的要求是給出一個 32 位的有符號整數,因此可以確定是int類型,但是32位int類型的范圍是[$-2^{31}, 2^{31}-1$], -2147483648-2147483647,那么問題來了,我提交代碼后,提示錯誤:

Exception in thread "main" java.lang.NumberFormatException: For input string: "9646324351"

意思就是無法將9646324351轉為int,很明顯給出的原始數字是1534236469,這是一個規范的int類型數值,然而反轉后9646324351很明顯超過了范圍。溢出了。當時我取巧了,既然是這個異常,直接在catch后return 0,機智如我,是個很人,提交,完美通過。

判斷整數溢出

說到底還是需要知道怎么做判斷啊,我的第一直覺是轉為BigDecimal,很明顯,這很方便且有效:

 /**
         * 方案二:轉為BigDecimal
         */
        BigDecimal b = new BigDecimal(sb.toString());
        if(b.compareTo(new BigDecimal(String.valueOf(Integer.MAX_VALUE))) > 0) {
           // 溢出了
        }else{
          
        }

sb.toString()就是需要判斷的字符串。

那么除了轉為BigDecimal,還有什么方式呢,肯定還有啦;
整數可以看作是相應位數上的數字做如下操作,比如123

  1. 0*10 + 1 = 1
  2. 1*10 + 2 = 12
  3. 12 * 10 + 3 = 123
    每次增加10倍,並加上各位數字,因此可以在每一次sum*10+digit之前做判斷。
if(Integer.MAX_VALUE/10 < sum || (Integer.MAX_VALUE/10 == sum && Integer.MAX_VALUE % 10 < digit)) {
                // 說明溢出
                return true;
            }

完整判斷代碼如下:

private boolean outOfRange(String str) {
        int length = str.length();
        if(length == 0){
            return false;
        }
        int index = 0;
        int sum = 0; // 記錄累加結果
        while(index < length) {
            int digit = str.charAt(index) - '0';
            // 這里假定str是合法的字符串,不需要進行digit合法性判斷

            if(Integer.MAX_VALUE/10 < sum || (Integer.MAX_VALUE/10 == sum && Integer.MAX_VALUE % 10 < digit)) {
                // 說明溢出
                return true;
            }
            // 說明還沒有溢出
            sum = sum * 10 + digit;
            index ++;
        }
        return false;
    }

參數str是需要判斷的字符串,這里沒有處理符號位,如果有-直接去掉,按照Integer.MAX_VALUE做比較同樣可以。同時函數也沒有考慮str中含有不合法的數字字符,重點關注溢出嘛。

LeetCode整數反轉

最后還是貼上整數反轉的代碼

package com.jiajia.m5;

import java.math.BigDecimal;

/**
 * @ClassName: ReverseInteger
 * @Author: fanjiajia
 * @Date: 2019/5/17 下午8:00
 * @Version: 1.0
 * @Description:
 */
public class ReverseInteger {

    public static void main(String[] args) {
        ReverseInteger r = new ReverseInteger();
        System.out.print(r.reverse(1534236469));
    }

    public int reverse(int x) {
        if(x == 0) {
            return 0;
        }
        char[] ch_arr = String.valueOf(x).toCharArray();
        StringBuilder sb = new StringBuilder();
        int end_index = ch_arr[0] == '-'? 1 : 0;
        boolean flag = ch_arr[ch_arr.length - 1] == '0'; // 最后一位為0
        for(int i = ch_arr.length - 1; i >= end_index; i--) {
            if(flag && ch_arr[i] == '0') {
                continue;
            }
            flag = false;
            sb.append(ch_arr[i]);
        }
        /**
         * 方案一:異常里面返回,也是夠了
         */
//        int result;
//        try {
//           result =  end_index == 1? -Integer.valueOf(sb.toString()) : Integer.valueOf(sb.toString());
//        }catch(NumberFormatException e) {
//            return 0;
//        }
//        return result;
        /**
         * 方案二:轉為BigDecimal
         */
//        BigDecimal b = new BigDecimal(sb.toString());
//        if(b.compareTo(new BigDecimal(String.valueOf(Integer.MAX_VALUE))) > 0) {
//            return 0;
//        }else{
//            return end_index == 1? -Integer.valueOf(sb.toString()) : Integer.valueOf(sb.toString());
//        }

        /**
         * 方案3:做溢出判斷
         */
        if(outOfRange(sb.toString())) {
            return 0;
        }else {
            return end_index == 1? -Integer.valueOf(sb.toString()) : Integer.valueOf(sb.toString());
        }
    }

    private boolean outOfRange(String str) {
        int length = str.length();
        if(length == 0){
            return false;
        }
        int index = 0;
        int sum = 0; // 記錄累加結果
        while(index < length) {
            int digit = str.charAt(index) - '0';
            // 這里假定str是合法的字符串,不需要進行digit合法性判斷

            if(Integer.MAX_VALUE/10 < sum || (Integer.MAX_VALUE/10 == sum && Integer.MAX_VALUE % 10 < digit)) {
                // 說明溢出
                return true;
            }
            // 說明還沒有溢出
            sum = sum * 10 + digit;
            index ++;
        }
        return false;
    }
}

有意思的是寫了個溢出判斷函數的效率還沒有直接catch異常來得高!!!

最后

研三畢業了,羡慕!!!
此致,敬禮!!!


免責聲明!

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



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