4.模拟计算器 实现四则运算
(1)中缀表达式转后缀表达式
- 什么是中缀表达式呢?
我们平时做数学题所列的标准四则运算表达式,例如:“9+(3-1)×3+10÷2” 就是一个中缀表达式
- 中缀表达式转后缀表达式的结果又是什么样子的呢?
“9 3 1 - 3 × + 10 2 ÷ +”
- 栈的作用: 进出运算符号
转换规则:
从左到右遍历中缀表达式的每一个数字和符号,若是数字,直接输出成为后缀表达式的一部分,若是运算符号,首先判断其与栈顶元素的优先级,如果是右括号或是优先级高于栈顶元素(乘除优于加减)的符号,直接入栈,否则,则将栈顶元素依次出栈并输出,并将当前符号入栈,直到栈空即输出后缀表达式为止。
以“9+(3-1)×3+10÷2”为例,挑选其中最复杂的两个步骤进行动图说明:
输出9,“+”入栈,“(” 直接入栈 <优先级最高>,输出3,“-”入栈,下一个符号为“)”,我们需要去找与之对应的左括号“(”,所以栈顶元素依次出栈,直至“(” 出栈为止,即输出“-”。
输出8,""入栈,输出2,“÷”、“+”依次出栈。
最终后缀表达式的输出结果为:“9 3 1 - 3 × + 10 2 ÷ +”
(2)后缀表达式计算结果
- 栈的作用: 进出运算数字
转换规则:
从左到右遍历后缀表达式的每个数字和符号,若为数字则进栈,若为符号,则将处于栈顶的两个数字出栈,进行相对应的加减乘除运算,将运算结果入栈,直到栈空得到最终计算结果。
仍然以“9 3 1 - 3 × + 10 2 ÷ +”后缀表达式为例简单描述这个过程:
9、3、1依次入栈,下一符号为“-”,则将3、1出栈进行3-1操作,将结果2入栈,同理继续进行3×2操作,将结果6入栈,直至得到最后结果20,将结果输出。
(3)附代码如下:
class Calculate {
//获取字符优先级:乘除优先于加减
private static int getPriority(char value) {
int result = 0;
switch (value) {
case '+':
case '-':
result = 1;
break;
case '*':
case '/':
result = 2;
break;
}
return result;
}
//加减乘除运算
private static int operator(int item1, int item2, char operate) {
int result = 0;
switch (operate) {
case '+':
result = item2 + item1;
break;
case '-':
result = item2 - item1;
break;
case '*':
result = item2 * item1;
break;
case '/':
result = item2 / item1;
break;
}
return result;
}
//中缀表达式转后缀表达式
public static String infixToPostfix(String str) { //9+(3-1)*3+10/2
String result = "";//返回最终结果
String split = " ";//空格分隔,用来区分数字的位数问题(可能存在多位情况)
boolean flag = false;//以空格对数据进行分割
Stack<Character> stack = new Stack<>();//Character类型的stack栈用于存放字符
for (int i = 0; i < str.length(); i++) {
char value = str.charAt(i);//获得str字符串中的每个字符
if(value>='0'&&value<='9'){
result+=value;
flag=true;
}else if(value==')'){//如果是'(',则下一位必然为字符,故无需判断flag
while (!(stack.peek()=='(')) {
result+=stack.pop();
}
stack.pop();
}else{//其他字符
if(flag==true){
result+=split;//以空格分隔数字与字符
flag=false;
}
//若栈空或运算符为'(',直接入栈
if (stack.isEmpty()||value=='(') {
stack.push(value);
continue;
}
//否则判断优先级后进行相关操作
//将优先级高的运算符直接入栈
if (getPriority(stack.peek()) < getPriority(value)) {
stack.push(value);
} else {//遇到栈顶符号比当前符号优先级高时,一直出栈直至当前符号优先级最高即可
while (!stack.isEmpty() && getPriority(stack.peek()) >= getPriority(value)) {
result += stack.peek();
stack.pop();
}
//将当前符号入栈操作
stack.push(value);
}
}
}
while (!stack.isEmpty()) {
result += stack.peek();
stack.pop();
}
return result;
}
//后缀表达式计算结果
public static int cal(String str) {
str=infixToPostfix(str);
Stack<Integer> stack = new Stack<>();//Integer类型的stack栈用于存放数字
for (int i = 0; i < str.length(); ) {
String subNumber = "";//保存数字
char value = str.charAt(i);
if (value == ' ') {
i++;
continue;
}
if (value >= '0' && value <= '9') {
while (value >= '0' && value <= '9') {//判断两位数或以上数字
subNumber += value;
i++;
value = str.charAt(i);//当前字符
}
stack.push(Integer.valueOf(subNumber));
if(value==' '){
i++;
}
} else {
int item1 = stack.pop();
int item2 = stack.pop();
int result=operator(item1,item2,value);
stack.push(result);
i++;
}
}
return stack.pop();
}
}
public class Calculater {
public static void main(String[] args) {
Calculate c=new Calculate();
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("请输入要计算的表达式:");
String str = scanner.next();
int result = c.cal(str);
// System.out.println(c.infixToPostfix(str));
System.out.println("计算结果:" + result);
}
}
}
运行结果: