You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中LeetCode字符串转整数(Integer)溢出检查原理解析

解析Java版LeetCode myAtoi中的溢出检查逻辑

我正在LeetCode上完成《String to Integer(atoi)》题目,需要实现myAtoi(string s)函数,将字符串转换为32位有符号整数(类似C/C++的atoi函数)。题目要求的算法步骤如下:

  • 读取并忽略所有前导空格;
  • 检查下一个字符是否为'-'或'+'以确定结果正负,默认正;
  • 读取后续数字直到遇到非数字字符或输入结束,其余字符串忽略;
  • 将读取到的数字转为整数,未读取到数字则结果为0,再调整符号;
  • 若整数超出32位有符号整数范围[-2^31, 2^31-1],则截断至该范围的边界值;
  • 返回最终整数。

注意:仅空格' '视为空白字符。

多数解法都是Python版本,我不清楚Java中Integer溢出检查的实现方式,看了在线Java解法后还是不理解其中的溢出检查逻辑,希望有人帮忙解释这段代码的工作原理。以下是该Java版本代码:

class Solution {
    public int myAtoi(String input) {
        int sign = 1; 
        int result = 0; 
        int index = 0;
        int n = input.length();
        
        // 跳过开头所有空格
        while (index < n && input.charAt(index) == ' ') { 
            index++; 
        }
        
        // 确定正负符号
        if (index < n && input.charAt(index) == '+') {
            sign = 1;
            index++;
        } else if (index < n && input.charAt(index) == '-') {
            sign = -1;
            index++;
        }
        
        // 遍历后续数字,遇到非数字则停止
        while (index < n && Character.isDigit(input.charAt(index))) {
            int digit = input.charAt(index) - '0';

            // 检查溢出/下溢条件
            if ((result > Integer.MAX_VALUE / 10) || 
                (result == Integer.MAX_VALUE / 10 && digit > Integer.MAX_VALUE % 10)) {     
                // 溢出返回MAX_VALUE,下溢返回MIN_VALUE
                return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
            }
            
            // 将当前数字追加到结果中
            result = 10 * result + digit;
            index++;
        }
        
        // 返回带符号的结果
        return sign * result;
    }
}

溢出检查逻辑详解

首先明确32位有符号整数的边界值:

  • Integer.MAX_VALUE = 2^31 - 1 = 2147483647
  • Integer.MIN_VALUE = -2^31 = -2147483648

代码中在每次将新数字加入结果前,都会先执行溢出检查,避免计算时直接触发溢出导致数值异常。下面拆解判断条件的两种情况:

情况1:result > Integer.MAX_VALUE / 10

Integer.MAX_VALUE / 10的计算结果是214748364(2147483647除以10取整)。如果当前result已经大于这个值,那么result * 10之后必然会超过2147483647——比如result是214748365,乘以10得到2147483650,远大于MAX_VALUE,不管后面加的数字是0-9中的哪一个,都会触发溢出。

情况2:result == Integer.MAX_VALUE / 10 && digit > Integer.MAX_VALUE % 10

当result刚好等于214748364时,result * 10得到2147483640,这时候要看新增的digit是多少。Integer.MAX_VALUE % 10是7(2147483647的最后一位数字),如果digit大于7(也就是8或9),那么10 * result + digit就会变成2147483648或2147483649,超过MAX_VALUE,触发溢出。

为什么不用负数直接判断?

代码里只用MAX_VALUE做判断,再根据sign返回对应边界值,是因为:
负数的边界Integer.MIN_VALUE绝对值是2147483648,比MAX_VALUE大1。当result是214748364且digit是8时,如果sign是-1,最终结果是-2147483648,刚好等于MIN_VALUE;如果digit是9,结果是-2147483649,超出范围,应该返回MIN_VALUE。而上面的判断逻辑刚好覆盖这种场景:只要触发条件,正数返回MAX_VALUE,负数返回MIN_VALUE,完美适配两种溢出情况。

这种提前检查的方式,避免了先计算10*result + digit导致的溢出(Java中整数溢出会按补码循环,溢出后数值会变成负数,反而难以判断),是更安全的溢出处理方式。

内容的提问来源于stack exchange,提问作者Spindoctor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 05:18:33