实现竖式除法时触发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位时,初始dividerLength为除数位数,被除数位数为dividerLength+1。进入while循环后,第一次执行dividerLength++使其等于被除数位数,此时循环本应退出,但如果触发variable < divider && variable < initVariable的条件,会再次执行dividerLength++,导致dividerLength超出被除数数字列表的最大索引(列表索引从0开始,最大索引为dividerLength),调用get(dividerLength)时抛出IndexOutOfBoundsException。其他潜在问题:
- 重复调用
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
相关产品推荐
相关产品推荐

