Java 实现字符串四则运算
程序员文章站
2022-03-31 11:07:03
...
手痒写写抄抄代码,看来需要好好复习下算法了。
一、测试代码
package cn.dt.algorithm.stack;
import org.junit.Assert;
import org.junit.Test;
/**
* @author DT
* @date 2020/7/28 14:43
*/
public class InfixExpressionTest {
@Test
public void testCalculator() {
InfixExpression infixExpression = new InfixExpression();
Assert.assertEquals(3 + 2 * 6 - 5 / 1, infixExpression.calculate("3 + 2 * 6 - 5 / 1"));
Assert.assertEquals(3 + 2, infixExpression.calculate("3 + 2"));
Assert.assertEquals(3 - 2, infixExpression.calculate("3 - 2"));
Assert.assertEquals(3 * 2, infixExpression.calculate("3 * 2"));
Assert.assertEquals(3 / 2, infixExpression.calculate("3 / 2"));
Assert.assertEquals(30 + 2 * 6, infixExpression.calculate("30 + 2 * 6"));
Assert.assertEquals(30 * 2 + 6, infixExpression.calculate("30 * 2 + 6"));
}
}
二、实现
1. 表达式处理类
package cn.dt.algorithm.stack;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
/**
* 表达式处理类
* 解析表达式,并使用计数器计算解析结果。
*
* @author DT
* @date 2020/7/28 13:25
*/
public class InfixExpression {
/**
* 表达式中数值与符号使用空格分隔
*/
private static final char SPLITTER = ' ';
/**
* 计算表达式的值
*
* @param expression 表达式,数值与符号之间是要空格隔开
* @return
*/
public int calculate(String expression) {
Calculator calculator = new Calculator();
String[] strings = StringUtils.split(expression, SPLITTER);
Arrays.stream(strings).forEach(s -> handleString(calculator, s));
return calculator.getResult();
}
/**
* 处理字符,数字和操作数分开处理。
* 当出现非数字和四则运算符试抛出 @UnsupportedOperationException 异常
*
* @param calculator
* @param s
*/
private void handleString(Calculator calculator, String s) {
if (isNumber(s)) {
calculator.addNum(Integer.valueOf(s));
} else if (isOperator(s)) {
calculator.addOperator(s);
} else {
throw new UnsupportedOperationException("非法字符:" + s);
}
}
/**
* 判断字符串是否是操作符
*
* @param s 字符
* @return 字符为四则运算符时返回 true
*/
private boolean isOperator(String s) {
return "+".equals(s) || "-".equals(s) || "*".equals(s) || "/".equals(s);
}
/**
* 判断是否是数字
*
* @param s 字符
* @return 如果是数字返回 true
*/
private boolean isNumber(String s) {
return s.matches("\\d+");
}
}
2. 计算类
/**
* 计算器,实现四则运算
*
* @author DT
* @date 2020/7/28 15:33
*/
public class Calculator {
/**
* 定义四则运算*别, “*” 和 “/"
*/
public static final int MAX_PRIORITY = 2;
/**
* 数值栈,用于存放操作数
*/
private Stack<Integer> numStack = new Stack<>();
/**
* 操作符栈, 用于存放操作符
*/
private Stack<String> operatorStack = new Stack<>();
public int getResult() {
while (!operatorStack.isEmpty()) {
calc();
}
return numStack.pop();
}
/**
* 从数值栈和操作符栈中取值进行计算, 并将结果压入操作数栈
*/
private void calc() {
int num2 = numStack.pop();
int num1 = numStack.pop();
String operator = operatorStack.pop();
int result = 0;
switch (operator) {
case "+":
result = num1 + num2;
break;
case "-":
result = num1 - num2;
break;
case "*":
result = num1 * num2;
break;
case "/":
result = num1 / num2;
break;
default:
throw new UnsupportedOperationException("非法操作符:" + operator);
}
numStack.push(result);
}
/**
* 获取操作数栈栈顶元素优先级
*
* @return 栈顶元素优先级
*/
private int getTopOperatorPriority() {
if (operatorStack.isEmpty()) {
return 0;
}
String s = operatorStack.peek();
return getOperatorPriority(s);
}
/**
* 获取操作符优先级
*
* @param s 操作符
* @return "+" ”-“ 返回 1,”*“ ”/" 返回 2. 否则抛出 @UnsupportedOperationException
*/
private int getOperatorPriority(String s) {
if ("+".equals(s) || "-".equals(s)) {
return 1;
} else if ("*".equals(s) || "/".equals(s)) {
return 2;
} else {
throw new UnsupportedOperationException("非法操作符:" + s);
}
}
/**
* 处理操作符
* 1. 如果操作数栈顶是最高优先级( “*”、“/"), 进行计算
* 2. 如果操作数栈不为空,且栈顶元素与当前操作符同级,进行计算
* 3. 将操作符入栈
*
* @param s
*/
public void addOperator(String s) {
if (!operatorStack.isEmpty() && getOperatorPriority(s) != MAX_PRIORITY) {
calc();
}
operatorStack.push(s);
}
/**
* 处理数值,将数值入栈
* <p>
* 然后判断下操作符栈顶元素,如果是*进行计算。
*
* @param num
*/
public void addNum(Integer num) {
numStack.push(num);
if (getTopOperatorPriority() == MAX_PRIORITY) {
calc();
}
}
}
参考
这位大哥写的清晰明了, 请移步 ——— 数据结构-栈的应用之中缀表达式的计算
上一篇: extern使用方法总结
下一篇: Linux下的tar压缩解压缩命令详解