美文网首页
Java判断整数溢出

Java判断整数溢出

作者: DuBetter | 来源:发表于2019-05-17 21:55 被阅读0次

    开题报告第一版写完发给老师了,熬了两周终于搞出来了,等着被怼了之后再改吧。晚上选了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异常来得高!!!


    image

    最后

    研三毕业了,羡慕!!!
    此致,敬礼!!!

    相关文章

      网友评论

          本文标题:Java判断整数溢出

          本文链接:https://www.haomeiwen.com/subject/leuaaqtx.html