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

实现竖式除法时触发java.lang.IndexOutOfBoundsException求助

竖式除法Java程序索引越界异常排查与修复

我开发了一个模拟竖式除法的Java程序,多数场景运行正常,但当被除数的位数仅比除数多一位,且被除数前几位与除数相近时,会抛出java.lang.IndexOutOfBoundsException异常,请求排查并解决该问题。

目前程序仅完成计算逻辑,还未实现竖式格式的字符串输出,需先解决该异常问题。

异常场景说明

  • 触发条件:被除数位数 = 除数位数 + 1,且被除数前几位与除数数值接近(例如999÷99、500÷49这类情况)
  • 正常场景:被除数与除数位数差距较大、或常规除法场景均能正常计算

原代码

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class Division {

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);
    int dividend = scan.nextInt();
    int divider = scan.nextInt();
    divisionEngine(dividend, divider);
    scan.close();
}

public static List<Integer> getDigits(int dividend) {
    List<Integer> digitArray = new ArrayList<>();

    while (dividend > 0) {
        digitArray.add(dividend % 10);
        dividend = dividend / 10;
    }
    Collections.reverse(digitArray);
    return digitArray;
}

public static int divisionEngine(int dividend, int divider) {
    StringBuilder builder = new StringBuilder();
    int dividerLength = String.valueOf(divider).length();
    int result = 0;
    int substraction = 0;
    int variable = Integer.parseInt(getDigits(dividend).subList(0, dividerLength).toString().replace("[", "")
            .replace("]", "").replace(", ", ""));
    int initVariable = variable;

    while (dividerLength != getDigits(dividend).size()) {
        result = Math.abs(variable / divider);
        builder.append(result);
        substraction = Math.abs(result * divider);
        variable = Integer.parseInt(variable - substraction + "".concat(getDigits(dividend).get(dividerLength++)
                .toString().replace("[", "").replace("]", "").replace(", ", "")));

        if (variable < divider && variable < initVariable) {
            variable = Integer.parseInt(variable + "".concat(getDigits(dividend).get(dividerLength++)
                    .toString().replace("[", "").replace("]", "").replace(", ", "")));
            builder.append(0);
        }

        if (substraction != 0 && variable != initVariable) {
            System.out.println(substraction + "\n" + variable);
        }
    }

    if (dividerLength == getDigits(dividend).size()) {
        result = Math.abs(variable / divider);
        substraction = Math.abs(result * divider);
        variable -= Math.abs(substraction);
        builder.append(result);
        result = Integer.parseInt(builder.toString());

        if (substraction != 0) {
            System.out.println(substraction + "\n" + variable);
        }
    }
    System.out.println("= " + result);

    return result;
}
}

问题根源

  1. 索引越界直接原因:
    当被除数仅比除数多1位时,初始dividerLength为除数位数,被除数位数为dividerLength+1。进入while循环后,第一次执行dividerLength++使其等于被除数位数,此时循环本应退出,但如果触发variable < divider && variable < initVariable的条件,会再次执行dividerLength++,导致dividerLength超出被除数数字列表的最大索引(列表索引从0开始,最大索引为dividerLength),调用get(dividerLength)时抛出IndexOutOfBoundsException。

  2. 其他潜在问题:

    • 重复调用getDigits(dividend),每次都重新拆分数字,效率低下且易引发不必要的对象创建。
    • 使用字符串拼接后转整数的方式更新variable,逻辑繁琐且存在格式风险(如前导零)。

修复方案及代码

核心修复点

  • 提前缓存被除数的数字列表,避免重复调用拆分方法。
  • 用数学运算代替字符串拼接更新variable,简化逻辑并提升可靠性。
  • 严格控制dividerLength的递增边界,在执行索引访问前确保不越界。
  • 修改循环条件为<而非!=,明确循环终止的边界条件。

修复后代码

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class Division {

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int dividend = scan.nextInt();
        int divider = scan.nextInt();
        divisionEngine(dividend, divider);
        scan.close();
    }

    public static List<Integer> getDigits(int dividend) {
        List<Integer> digitArray = new ArrayList<>();
        // 处理被除数为0的特殊情况
        if (dividend == 0) {
            digitArray.add(0);
            return digitArray;
        }
        while (dividend > 0) {
            digitArray.add(dividend % 10);
            dividend = dividend / 10;
        }
        Collections.reverse(digitArray);
        return digitArray;
    }

    public static int divisionEngine(int dividend, int divider) {
        StringBuilder builder = new StringBuilder();
        // 提前缓存被除数的数字列表,避免重复拆分
        List<Integer> dividendDigits = getDigits(dividend);
        int dividerLength = String.valueOf(divider).length();
        int dividendLength = dividendDigits.size();
        int result = 0;
        int substraction = 0;
        
        // 用数学运算初始化variable,替代字符串拼接转整数
        int variable = 0;
        for (int i = 0; i < dividerLength; i++) {
            variable = variable * 10 + dividendDigits.get(i);
        }
        int initVariable = variable;

        // 用<明确循环边界,避免多次递增后越界
        while (dividerLength < dividendLength) {
            result = Math.abs(variable / divider);
            builder.append(result);
            substraction = Math.abs(result * divider);
            // 数学方式更新variable,无需字符串操作
            variable = (variable - substraction) * 10 + dividendDigits.get(dividerLength);
            dividerLength++;

            // 检查是否还有剩余数字,再执行补0操作,避免索引越界
            if (variable < divider && dividerLength < dividendLength) {
                variable = variable * 10 + dividendDigits.get(dividerLength);
                dividerLength++;
                builder.append(0);
            }

            if (substraction != 0 && variable != initVariable) {
                System.out.println(substraction + "\n" + variable);
            }
        }

        if (dividerLength == dividendLength) {
            result = Math.abs(variable / divider);
            substraction = Math.abs(result * divider);
            variable -= Math.abs(substraction);
            builder.append(result);
            result = Integer.parseInt(builder.toString());

            if (substraction != 0) {
                System.out.println(substraction + "\n" + variable);
            }
        }
        System.out.println("= " + result);

        return result;
    }
}

修复说明

  • 新增被除数为0的处理逻辑,完善边界场景。
  • 缓存数字列表,大幅减少重复计算,提升程序效率。
  • 数学运算替代字符串操作,简化逻辑同时避免格式错误。
  • 补0操作前增加边界判断,从根本上杜绝索引越界的可能。
  • 循环条件更严谨,确保循环在合理范围内执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 06:35:37