Java命令行计算器sqrt运算符实现报错,求解决方案
Java命令行计算器sqrt处理异常修复方案
错误根源
- 变量名冲突:处理
sqrt的point变量与后续解析数字的point变量重名,导致解析阶段的point初始值被错误设置为处理完sqrt后的位置,而转换后的input长度短于原输入,触发substring越界(如报错中的Range [6, 1))。 - sqrt处理逻辑缺陷:仅提取
sqrt后的单个字符,无法处理多位数(如sqrt 16会被错误转换为1^0.5),且硬编码索引p+5易因格式变化出错。 - 重复添加数字:循环结束后额外执行
nums.add(Float.parseFloat(input.substring(point))),导致重复添加最后一个数字,甚至在point超出input长度时触发异常。 - 未处理乘法符号
x:用户示例中的6x2^3-3未被转换为标准乘法符号*,会导致解析失败。
修复后的完整代码
import java.util.ArrayList; import java.util.Scanner; public class Calculator { public static void main(String[] args) { int counter = 0; String[] operators = {"^", "/", "*", "+", "-"}; Scanner myScan = new Scanner(System.in); String inputs = myScan.nextLine(); ArrayList<Float> nums = new ArrayList<>(); ArrayList<String> ops = new ArrayList<>(); // 先处理乘法符号x为*,兼容用户示例写法 inputs = inputs.replace('x', '*'); float currentNum; // 改名避免与后面解析数字的point变量冲突 int sqrtPoint = 0; String input = ""; // 修复sqrt处理逻辑:提取完整数字,支持多位数和小数 for (int p = 0; p <= inputs.length() - 4; p++) { if (inputs.startsWith("sqrt", p)) { // 添加sqrt之前的内容 input += inputs.substring(sqrtPoint, p); // 找到sqrt后面数字的起始位置(跳过空格) int numStart = p + 4; // 找到数字的结束位置 int numEnd = numStart; while (numEnd < inputs.length() && (Character.isDigit(inputs.charAt(numEnd)) || inputs.charAt(numEnd) == '.')) { numEnd++; } // 提取完整数字并转换为^0.5形式 String num = inputs.substring(numStart, numEnd); input += num + "^0.5"; // 更新sqrtPoint到数字结束位置 sqrtPoint = numEnd; // 跳过已处理的数字部分,避免重复遍历 p = numEnd - 1; } } // 添加剩余未处理的内容 input += inputs.substring(sqrtPoint); System.out.println("转换后表达式:" + input); // 解析数字和运算符,使用独立的point变量 int point = 0; for (int i = 0; i < input.length(); i++) { char c = input.charAt(i); // 判断是否为运算符,或处理最后一个字符的情况 if ((!Character.isDigit(c) && c != '.') || i == input.length() - 1) { try { // 处理最后一个字符时,截取到字符串末尾 int endIndex = (i == input.length() - 1) ? input.length() : i; currentNum = Float.parseFloat(input.substring(point, endIndex)); nums.add(currentNum); point = i + 1; } catch (Exception e) { System.out.println("无效数字:" + input.substring(point, i)); return; } // 如果不是最后一个字符,添加对应的运算符 if (i != input.length() - 1) { for (String op : operators) { if (input.startsWith(op, i)) { ops.add(op); // 预留多字符运算符的处理逻辑 i += op.length() - 1; break; } } } } } // 按照运算优先级计算表达式 for (String operator : operators) { for (int j = 0; j < ops.size(); j++) { String op = ops.get(j); if (op.equals(operator)) { float num1 = nums.get(j); float num2 = nums.get(j + 1); float result = switch (op) { case "^" -> (float) Math.pow(num1, num2); case "/" -> num1 / num2; case "*" -> num1 * num2; case "+" -> num1 + num2; case "-" -> num1 - num2; default -> 0; }; nums.set(j, result); nums.remove(j + 1); ops.remove(j); j--; } } } float answer = nums.get(0); System.out.println("计算结果:" + answer); myScan.close(); } }
关键修改说明
- 重命名
point变量为sqrtPoint,彻底避免变量冲突问题。 - 重构
sqrt处理逻辑:通过循环提取完整数字,支持多位数和小数,替换易出错的硬编码索引。 - 移除重复添加数字的冗余代码,避免重复计算或越界。
- 添加
x到*的转换逻辑,兼容用户示例中的乘法写法。 - 优化数字解析逻辑,统一处理普通字符和最后一个字符的截取,减少异常触发点。
内容的提问来源于stack exchange,提问作者The-Senate_V
相关产品推荐
相关产品推荐

