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

最后

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