(Java語言)用棧實現的支援括號的四則運算計算器
小需求:編寫一個簡單的計算器,該計算器目前只需要支援單位正整數的加、減、乘、除運算,並支援用括號表示優先級別。和我們小
學時學過的算術規則一致,乘法和除法的優先順序一樣,加法和減法的優先順序一樣。乘除法的優先順序高於加減法。括號的優先順序
最高。同一優先順序的運算順序為自左向右。要求提供一個名為eval的API,輸入字串型別的表示式,輸出整數型別的運算結果。
實現思路:
將運算表示式(中綴)轉換成字尾表示式,並用棧計算結果,處理步驟:
一、解析輸入的運算表示式中的運算元和運算子,並按照原有順序存於一個數組,結果這個數組裡存的是中綴表示式
二、將步驟一的中綴表示式結果轉成字尾表示式,需要設定一個棧來臨時存放運算子,處理步驟是:
為運算子定義優先順序:( + - * /
0 1 1 2 2
從原表示式求字尾式的規則為:
1.設定運算子棧
2.掃描表示式,若當前字元是運算元,則直接傳送給字尾表示式;
3.若當前字元為運算子且優先順序大於棧頂運算子,則進棧,否則退出棧頂運算子並將其傳送給字尾式。然後將當前運算子放入棧中。
4.若掃描完表示式,則將棧中的全部運算子依次傳送給字尾式。
5.若當前字元為"(",進棧。
6.若當前字元為")",則從棧頂起,依次將棧中運算子出棧傳送給ie字尾式,直到碰到"("。將棧中"("出棧,不需要傳送給字尾式。然後繼續掃描表示式。
三、根據字尾表示式計算結果,也要設定一個棧用於臨時存放運算元,處理步驟是:
1、掃描表示式,若當前字元是運算元,則進棧
2、若當前字元為運算子,則取兩次棧頂的運算元,第一次取棧頂運算元作為運算子後面的運算元,第二次取棧頂運算元作為運算子前面的運算元,計算所組成表示式的結果,然後將結果進棧
3、若掃描完表示式,則存於棧頂的就是最終的結果。
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
*
Created by neo on 2018/3/27. */
public class Calculator
{
public static int eval(String
expression) {
List<CalcItem>
middleExpression = initCalcExpression(expression);
List<CalcItem>
postfixExpression = transferToPostfixExpression(middleExpression);
return evaluatePostfixExpression(postfixExpression);
}
private static List<CalcItem>
initCalcExpression(String expression) {
List<CalcItem>
result = new ArrayList<>();
for ( int i
= 0 ;
i < expression.length(); i++) {
String
item = expression.substring(i, i + 1 );
if (Operator.isOperator(item))
{
result.add( new Operator(item));
} else if (Number.isNumber(item))
{
result.add( new Number(item));
}
}
return result;
}
private static List<CalcItem>
transferToPostfixExpression(List<CalcItem> middleExpression) {
List<CalcItem>
result = new ArrayList<>();
Stack<CalcItem>
calcStack = new Stack<>();
for (CalcItem
aMiddleExpression : middleExpression) {
aMiddleExpression.postfixTransfer(result,
calcStack);
}
while (!calcStack.empty())
{
result.add(calcStack.pop());
}
return result;
}
private static int evaluatePostfixExpression(List<CalcItem>
postfixExpression) {
Integer
numLeft, numberRight, result;
Stack<Number>
numberStack = new Stack<>();
for (CalcItem
item : postfixExpression) {
if (item instanceof Number)
{
numberStack.push((Number)
item);
} else {
numberRight
= numberStack.pop().value();
numLeft
= numberStack.pop().value();
result
= ((Operator) item).calc(numLeft, numberRight);
numberStack.push( new Number(result.toString()));
}
|