58,441
社区成员
发帖
与我相关
我的任务
分享
BufferedReader br = new BufferedReader(new FileReader(new File(path)));
String line = br.readLine();
while (line != null) {
System.out.println(line);
line = br.readLine();
}
br.close();
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
public class Calculator {
private static final Map<String, Integer> OP_LEVEL = new HashMap<>();
static {
OP_LEVEL.put("+", 1);
OP_LEVEL.put("-", 1);
OP_LEVEL.put("*", 2);
OP_LEVEL.put("/", 2);
OP_LEVEL.put("(", 3);
OP_LEVEL.put(")", 3);
}
public static void main(String[] args) {
// String src = "10+20*(5+6)-70+6/3";
String src = "16/2+(9-4)*17";
Calculator c = new Calculator();
System.out.println(src + "=" + c.calc(src));
}
/**
* 对输入字符串执行简单四则运算
*
* @param ex
* 四则运算表达式
* @return
*/
public double calc(String ex) {
// 1)求输入串的逆序。
ex = reverse(ex);
// 一步循环中要处理的字符
char ch;
// 用于保存数字的临时变量
StringBuilder builder = new StringBuilder();
// 操作数栈
Stack<Double> operand = new Stack<>();
// 运算符栈
Stack<Character> operator = new Stack<>();
// 执行单步运算的临时变量(操作数1,操作数2,中间结果)
double num1, num2, tmp;
// 执行单步操作的运算符
char op;
// 2)检查输入的每一个字符
for (int i = 0; i < ex.length(); i++) {
ch = ex.charAt(i);
if (isNumber(ch)) {
// 3)假如是数字,保存到临时变量中。
// 因为字符串逆序导致数字也是倒序的,所以,在将字符添加到StringBuilder中时,总是增加到头部。
builder.insert(0, ch);
} else {
// 如果保存数字的临时变量不空,则将它转成Double值,压入操作数栈中。
if (builder.length() > 0) {
operand.push(Double.parseDouble(builder.toString()));
builder = new StringBuilder();
}
if (ch == ')') {
// 4)假如是闭括号,将它压栈。
operator.push(ch);
} else {
if (isOperator(ch)) {
// 5)假如是运算符,则
if (operator.isEmpty()) {
// i)假如栈空,此运算符入栈。
operator.push(ch);
} else if (operator.peek() == ')') {
// ii)假如栈顶是闭括号,此运算符入栈。
operator.push(ch);
} else if (compareOperator(ch, operator.peek()) >= 0) {
// iii)假如它的优先级高于或等于栈顶运算符,此运算符入栈。
operator.push(ch);
} else {
// iv)否则,栈顶运算符出栈执行运算,重复步骤5。
while (!operator.isEmpty() && compareOperator(ch, operator.peek()) < 0) {
num1 = operand.pop();
num2 = operand.pop();
op = operator.pop();
tmp = step(op, num1, num2);
operand.push(tmp);
}
operator.push(ch);
}
} else {
if (ch == '(') {
// 6)假如是开括号,栈中运算符逐个出栈执行运算,直到遇到闭括号,闭括号出栈并丢弃。
while (operator.peek() != ')') {
num1 = operand.pop();
num2 = operand.pop();
op = operator.pop();
tmp = step(op, num1, num2);
operand.push(tmp);
// 直到运算符栈为空,还没有见到‘闭括号’,证明表达式格式有问题:括号不配对。
if (operator.isEmpty()) {
throw (new Error("四则运算表达式中存在不匹配的括号!"));
}
}
operator.pop();
} else {
// 存在不是括号、不是运算符、不是数字的字符
throw (new Error("四则运算表达式中存在非法字符!"));
}
}
}
}
}
if (builder.length() > 0) {
operand.push(Double.parseDouble(builder.toString()));
}
// 8)输入串处理完毕,栈中剩余的所有操作符出栈执行运算。
while (!operator.isEmpty()) {
num1 = operand.pop();
num2 = operand.pop();
op = operator.pop();
tmp = step(op, num1, num2);
operand.push(tmp);
}
return operand.pop();
}
/**
* 求输入串的逆序
*
* @param src
* @return
*/
private String reverse(String src) {
StringBuilder builder = new StringBuilder(src);
builder.reverse();
return builder.toString();
}
/**
* 判断一个字符是否为运算符
*
* @param ch
* @return
*/
private boolean isOperator(char ch) {
char[] operators = new char[] { '+', '-', '*', '/' };
for (int i = 0; i < operators.length; i++) {
if (ch == operators[i]) {
return true;
}
}
return false;
}
/**
* 判断字符是否是数字
*
* @param ch
* @return
*/
private boolean isNumber(char ch) {
return ch > 47 && ch < 58;
}
/**
* 比较运算符的优先级
*
* @param op1
* 运算符1
* @param op2
* 运算符2
* @return 1(运算符1优先级高)/0(二者优先级相同)/-1(运算符2优先级高)
*/
private int compareOperator(char op1, char op2) {
int op1_level = OP_LEVEL.get(op1 + "");
int op2_level = OP_LEVEL.get(op2 + "");
if (op1_level > op2_level) {
return 1;
} else if (op1_level < op2_level) {
return -1;
} else {
return 0;
}
}
/**
* 执行一步运算
*
* @param op
* 运算符
* @param num1
* 操作数1
* @param num2
* 操作数2
* @return
*/
private double step(char op, double num1, double num2) {
switch (op) {
case '+':
return num1 + num2;
case '-':
return num1 - num2;
case '*':
return num1 * num2;
case '/':
return num1 / num2;
default:
if (op == ')') {
throw (new Error("四则运算表达式中存在不匹配的括号!"));
} else {
throw (new Error("四则运算表达式中存在非法的字符!"));
}
}
}
}