【具体要求】
用户从键盘输入一个表达式,表达式中可以包含以下要素:
(1) 数值:包括整数和实数,数值可带正、负号。
(2) 一般运算符:正号、负号、加、减、乘、除、求余和乘方,其中可以包括括号。
(3) 单词(即运算函数):abs、sqrt、exp、ln、log10、sin、cos和tanh。
程序首先判断该表达式语法是否正确,如果不正确则结束程序运行;否则计算出该表达式的值,并将结果显示在屏幕上。
求解答。这是个复杂表达式求值的程序,输入中缀表达式,程序会转换成后缀表达式并求值,代码大致写出来了,注释也有。简单的运算可以执行,但是复杂一点就不行了。
下面两张是运行结果,后缀表达式转换错了,但是不知道怎么改。
,
import java.util.Scanner;
import java.util.Stack;
import java.lang.Math;
public class ExpressionEvaluator {
private static final String OPERATORS = "+-*/%^";
private static final int[] PRECEDENCE = {1, 1, 2, 2, 3, 4};
// 定义运算函数的名称
private static final String FUNCTIONS = "abs sqrt exp ln log10 sin cos tanh";
// 判断一个字符是否是运算符
private static boolean isOperator(char ch) {
return OPERATORS.indexOf(ch) != -1;
}
// 判断一个字符串是否是运算函数
private static boolean isFunction(String str) {
return FUNCTIONS.indexOf(str) != -1;
}
// 比较两个运算符的优先级
private static boolean hasHigherPrecedence(char op1, char op2) {
return PRECEDENCE[OPERATORS.indexOf(op1)] > PRECEDENCE[OPERATORS.indexOf(op2)];
}
// 对两个数值进行运算
private static double applyOperator(char op, double num1, double num2) {
switch (op) {
case '+':
return num1 + num2;
case '-':
return num1 - num2;
case '*':
return num1 * num2;
case '/':
if (num2 == 0) {
throw new ArithmeticException("除数不能为零");
}
return num1 / num2;
case '%':
return num1 % num2;
case '^':
return Math.pow(num1, num2);
default:
throw new IllegalArgumentException("无效的运算符: " + op);
}
}
// 对一个数值进行运算函数
private static double applyFunction(String func, double num) {
switch (func) {
case "abs":
return Math.abs(num);
case "sqrt":
return Math.sqrt(num);
case "exp":
return Math.exp(num);
case "ln":
return Math.log(num);
case "log10":
return Math.log10(num);
case "sin":
return Math.sin(num);
case "cos":
return Math.cos(num);
case "tanh":
return Math.tanh(num);
default:
throw new IllegalArgumentException("无效的运算函数: " + func);
}
}
// 将中缀表达式转换为后缀表达式
private static String convertToPostfix(String infix) {
StringBuilder postfix = new StringBuilder();
Stack<Character> operatorStack = new Stack<>();
for (int i = 0; i < infix.length(); i++) {
char ch = infix.charAt(i);
// 跳过空格
if (ch == ' ') {
continue;
}
// 如果是数字或小数点,直接追加到后缀表达式
if (Character.isDigit(ch) || ch == '.') {
postfix.append(ch);
}
// 如果是字母,可能是运算函数,需要读取整个单词,并追加到后缀表达式
else if (Character.isLetter(ch)) {
StringBuilder word = new StringBuilder();
while (i < infix.length() && Character.isLetter(infix.charAt(i))) {
word.append(infix.charAt(i));
i++;
}
i--; // 回退一位,因为循环结束时多读了一个字符
// 如果是运算函数,追加到后缀表达式,并在后面加一个空格
if (isFunction(word.toString())) {
postfix.append(word).append(' ');
} else {
throw new IllegalArgumentException("无效的运算函数: " + word);
}
}
// 如果是左括号,压入栈中
else if (ch == '(') {
operatorStack.push(ch);
}
// 如果是右括号,弹出栈中的运算符,直到遇到左括号,并追加到后缀表达式
else if (ch == ')') {
while (!operatorStack.isEmpty() && operatorStack.peek() != '(') {
postfix.append(' ').append(operatorStack.pop());
}
if (operatorStack.isEmpty()) {
throw new IllegalArgumentException("不匹配的括号");
}
operatorStack.pop(); // 弹出左括号
// 新增的语句: 在每个括号内的表达式后面加上一个空的括号,以区分运算符
postfix.append(" ( )");
}
// 如果是运算符,需要考虑优先级
else if (isOperator(ch)) {
// 在追加运算符之前,先追加一个空格,
postfix.append(' ');
// 弹出栈中所有优先级高于或等于当前运算符的运算符,追加到后缀表达式
while (!operatorStack.isEmpty() && operatorStack.peek() != '(' && hasHigherPrecedence(operatorStack.peek(), ch)) {
postfix.append(' ').append(operatorStack.pop());
}
// 新增的判断条件: 如果栈顶是运算函数,也弹出,追加到后缀表达式
while (!operatorStack.isEmpty() && isFunction(Character.toString(operatorStack.peek()))) {
postfix.append(' ').append(operatorStack.pop());
}
// 将当前运算符压入栈中
operatorStack.push(ch);
}
// 如果是其他字符,抛出异常
else {
throw new IllegalArgumentException("无效的字符: " + ch);
}
}
// 弹出栈中剩余的运算符,追加到后缀表达式
while (!operatorStack.isEmpty()) {
char op = operatorStack.pop();
if (op == '(') {
throw new IllegalArgumentException("不匹配的括号");
}
postfix.append(' ').append(op);
}
// 返回后缀表达式
return postfix.toString();
}
// 计算后缀表达式的值
private static double evaluatePostfix(String postfix) {
Stack<Double> operandStack = new Stack<>();
for (String token : postfix.split("\\s+")) {
// 如果是空字符串,跳过
if (token.isEmpty()) {
continue;
}
// 如果是数值,压入栈中
if (Character.isDigit(token.charAt(0))) {
operandStack.push(Double.parseDouble(token));
}
// 如果是运算函数,弹出一个数值,进行运算,然后将结果压入栈中
else if (isFunction(token)) {
if (operandStack.isEmpty()) {
throw new IllegalArgumentException("缺少运算数");
}
double num = operandStack.pop();
operandStack.push(applyFunction(token, num));
}
// 如果是运算符,弹出两个数值,进行运算,然后将结果压入栈中
else if (isOperator(token.charAt(0))) {
if (operandStack.size() < 2) {
throw new IllegalArgumentException("缺少运算数");
}
double num2 = operandStack.pop();
double num1 = operandStack.pop();
operandStack.push(applyOperator(token.charAt(0), num1, num2));
}
// 如果是其他字符串,抛出异常
else {
throw new IllegalArgumentException("无效的字符串: " + token);
}
}
// 如果栈中只剩一个数值,那就是最终结果
if (operandStack.size() == 1) {
return operandStack.pop();
}
// 如果栈中还有多个数值,说明表达式有误
else {
throw new IllegalArgumentException("多余的运算数");
}
}
// 主函数,从键盘输入一个表达式,计算并显示结果
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个表达式:");
String expression = scanner.nextLine();
scanner.close();
try {
String postfix = convertToPostfix(expression);
System.out.println("后缀表达式为: " + postfix);
double result = evaluatePostfix(postfix);
System.out.println("运算结果为: " + result);
} catch (Exception e) {
System.out.println("表达式有误: " + e.getMessage());
}
}}