单行输入简易Java计算器报错及功能异常求助
简易Java计算器问题排查与修复
原始代码
package kotauto; import java.util.ArrayList; import java.util.Scanner; import java.util.concurrent.TimeUnit; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; public class calculator { static double addition(int a, int b) { return a + b; } static double subtraction(int a, int b) { return a - b; } static double multiplication(int a, int b) { return a * b; } static double division(int a, int b) { return a / b; } static double exponentiation(int a, int b) { double z=1; for(int i=1; i<=b; i++) { z= z*a; } return z; } static double root_extraction(double a) { return Math.sqrt(a); } public static void main(String[] args) { System.out.print("WELCOME TO THE CALCULATOR"+'\n'); Scanner s = new Scanner(System.in); // scanner ArrayList<Character> cal = new ArrayList<>(); String z = s.next(); for(int i=0; i<z.length(); i++) { cal.add(z.charAt(i)); } int num1 = 0; int j =1; int x = 0; for(int i=0; i<z.length(); i++) { for(int k=0; k<z.length(); k++) { if(!Character.isDigit(cal.get(k))) { j =(int)Math.pow(10, k-1); break; } else { x++; } } if(Character.isDigit(cal.get(i))) { int n = Character.getNumericValue(cal.get(i)); num1 += j*n; j=j/10; } else { break; } } int num2= 0; int l =1; for(int i=0; i<z.length(); i++) { for(int k=0; k<z.length(); k++) { if(!Character.isDigit(cal.get(k))) { l =(int)Math.pow(10, k-1); break; } } if(Character.isDigit(cal.get(i))) { int n = Character.getNumericValue(cal.get(i)); num2 += l*n; l=l/10; } } switch(cal.get(x-1)) { case '+': { System.out.println(addition(num1, num2)); break; } case'-': { System.out.println(subtraction(num1, num2)); break; } case'/': { System.out.println(division(num1, num2)); break; } case '*': { System.out.println(multiplication(num1, num2)); break; } case '^': { System.out.println(exponentiation(num1, num2)); break; } case's': { System.out.println(root_extraction(num1)); break; } } s.close(); } }
遇到的问题
- 输入多位数时,
switch(cal.get(x-1))行抛出java.lang.IndexOutOfBoundsException异常; - 输入一位数时,加法运算会把第一个数重复相加,乘法结果会多算第一个数的平方,其他运算大概率也存在异常;
- 开方(root_extraction)功能设计不合理,必须在's'后输入随机数才能避免编译异常。
仅尝试调整过switch(cal.get(x-1))语句,未解决问题。第一次使用Stack Overflow,代码格式不佳请见谅。
问题原因与修复方案
1. 多位数输入索引越界
原因:x变量在嵌套循环里被反复累加,导致其值远大于运算符的实际索引,调用cal.get(x-1)必然越界。
修复:直接遍历字符列表,定位第一个非数字字符(即运算符)的索引:
int opIndex = -1; for (int i = 0; i < cal.size(); i++) { if (!Character.isDigit(cal.get(i))) { opIndex = i; break; } } // 后续switch改用这个索引 switch(cal.get(opIndex)) { // 原有case逻辑 }
2. 一位数运算重复计算
原因:计算num2时没有从运算符后开始读取,而是从头遍历整个输入串,导致num2和num1值完全相同,出现重复计算。
修复:分别从开头到运算符前、运算符后到结尾读取两个数字,逻辑更简单可靠:
// 计算第一个数 int num1 = 0; for (int i = 0; i < opIndex; i++) { num1 = num1 * 10 + Character.getNumericValue(cal.get(i)); } // 计算第二个数 int num2 = 0; for (int i = opIndex + 1; i < cal.size(); i++) { num2 = num2 * 10 + Character.getNumericValue(cal.get(i)); }
3. 开方功能设计不合理
原因:开方是单目运算,不需要第二个数,但当前逻辑强制要求输入s后加数字,否则会报错。
修复:单独处理开方逻辑,判断第一个字符为s时,直接读取后续数字计算开方,无需走双目运算流程:
// 优先处理开方单目运算 if (cal.get(0) == 's') { double num = 0; for (int i = 1; i < cal.size(); i++) { num = num * 10 + Character.getNumericValue(cal.get(i)); } System.out.println(root_extraction(num)); s.close(); return; // 结束程序,不执行后续双目运算逻辑 }
完整修复后的代码
package kotauto; import java.util.ArrayList; import java.util.Scanner; public class Calculator { // 类名首字母大写,符合Java编码规范 static double addition(int a, int b) { return a + b; } static double subtraction(int a, int b) { return a - b; } static double multiplication(int a, int b) { return a * b; } static double division(int a, int b) { // 新增除零判断,避免运行时异常 if (b == 0) { System.out.println("错误:不能除以0"); return Double.NaN; } return (double)a / b; // 强制转double,避免整数除法丢失精度 } static double exponentiation(int a, int b) { return Math.pow(a, b); // 简化幂运算实现 } static double root_extraction(double a) { if (a < 0) { System.out.println("错误:不能对负数开方"); return Double.NaN; } return Math.sqrt(a); } public static void main(String[] args) { System.out.println("WELCOME TO THE CALCULATOR"); Scanner s = new Scanner(System.in); ArrayList<Character> cal = new ArrayList<>(); String input = s.next(); for (int i = 0; i < input.length(); i++) { cal.add(input.charAt(i)); } // 处理开方单目运算 if (cal.get(0) == 's') { double num = 0; for (int i = 1; i < cal.size(); i++) { num = num * 10 + Character.getNumericValue(cal.get(i)); } System.out.println(root_extraction(num)); s.close(); return; } // 寻找双目运算符位置 int opIndex = -1; for (int i = 0; i < cal.size(); i++) { if (!Character.isDigit(cal.get(i))) { opIndex = i; break; } } // 处理无有效运算符的情况 if (opIndex == -1) { System.out.println("错误:未找到有效运算符"); s.close(); return; } // 计算第一个操作数 int num1 = 0; for (int i = 0; i < opIndex; i++) { num1 = num1 * 10 + Character.getNumericValue(cal.get(i)); } // 计算第二个操作数 int num2 = 0; for (int i = opIndex + 1; i < cal.size(); i++) { num2 = num2 * 10 + Character.getNumericValue(cal.get(i)); } // 执行对应运算 switch(cal.get(opIndex)) { case '+': System.out.println(addition(num1, num2)); break; case '-': System.out.println(subtraction(num1, num2)); break; case '/': System.out.println(division(num1, num2)); break; case '*': System.out.println(multiplication(num1, num2)); break; case '^': System.out.println(exponentiation(num1, num2)); break; default: System.out.println("错误:不支持的运算符"); } s.close(); } }
内容的提问来源于stack exchange,提问作者Bartek Kopyt
相关产品推荐
相关产品推荐

