請問: 計算機底層是如何運算獲得結果的? 注意不是簡單的把算式列出運算,由於咱們看這個算式程序員
7 * 2 * 2 - 5express
可是計算機怎麼理解這個算式的(對計算機而言,它接收到的就是一個字符串)數組
須要用到 數棧 和 符號棧this
public class Calculator { public static void main(String[] args) { //根據前面老師思路,完成表達式的運算 String expression = "7*2*2-5+1-5+3-4"; // 15//如何處理多位數的問題? //建立兩個棧,數棧,一個符號棧 ArrayStack2 numStack = new ArrayStack2(10); ArrayStack2 operStack = new ArrayStack2(10); //定義須要的相關變量 int index = 0;//用於掃描 int num1 = 0; int num2 = 0; int oper = 0; int res = 0; char ch = ' '; //將每次掃描獲得char保存到ch String keepNum = ""; //用於拼接 多位數 //開始while循環的掃描expression while(true) { //依次獲得expression 的每個字符 ch = expression.substring(index, index+1).charAt(0);//expression.substring(0, 8)取值爲index=0到index=7之間。 //判斷ch是什麼,而後作相應的處理 if(operStack.isOper(ch)) {//若是是運算符 //判斷當前的符號棧是否爲空 if(!operStack.isEmpty()) { //若是符號棧有操做符,就進行比較,若是當前的操做符的優先級小於或者等於棧中的操做符,就須要從數棧中pop出兩個數, //在從符號棧中pop出一個符號,進行運算,將獲得結果,入數棧,而後將當前的操做符入符號棧 if(operStack.priority(ch) <= operStack.priority(operStack.peek())) { num1 = numStack.pop(); num2 = numStack.pop(); oper = operStack.pop(); res = numStack.cal(num1, num2, oper); //把運算的結果如數棧 numStack.push(res); //而後將當前的操做符入符號棧 operStack.push(ch); } else { //若是當前的操做符的優先級大於棧中的操做符, 就直接入符號棧. operStack.push(ch); } }else { //若是爲空直接入符號棧.. operStack.push(ch); // 1 + 3 } } else { //若是是數,則直接入數棧 //numStack.push(ch - 48); //? "1+3" '1' => 1 //分析思路 //1. 當處理多位數時,不能發現是一個數就當即入棧,由於他多是多位數 //2. 在處理數,須要向expression的表達式的index 後再看一位,若是是數就進行掃描,若是是符號才入棧 //3. 所以咱們須要定義一個變量 字符串,用於拼接 //處理多位數 keepNum += ch; //若是ch已是expression的最後一位,就直接入棧 if (index == expression.length() - 1) { numStack.push(Integer.parseInt(keepNum)); }else{ //判斷下一個字符是否是數字,若是是數字,就繼續掃描,若是是運算符,則入棧 //注意是看後一位,不是index++ if (operStack.isOper(expression.substring(index+1,index+2).charAt(0))) { //若是後一位是運算符,則入棧 keepNum = "1" 或者 "123" numStack.push(Integer.parseInt(keepNum)); //重要的!!!!!!, keepNum清空 keepNum = ""; } } } //讓index + 1, 並判斷是否掃描到expression最後. index++; if (index >= expression.length()) { break; } } //當表達式掃描完畢,就順序的從 數棧和符號棧中pop出相應的數和符號,並運行. while(true) { //若是符號棧爲空,則計算到最後的結果, 數棧中只有一個數字【結果】 if(operStack.isEmpty()) { break; } num1 = numStack.pop(); num2 = numStack.pop(); oper = operStack.pop(); res = numStack.cal(num1, num2, oper); numStack.push(res);//入棧 } //將數棧的最後數,pop出,就是結果 int res2 = numStack.pop(); System.out.printf("表達式 %s = %d", expression, res2); } } //先建立一個棧,直接使用前面建立好 //定義一個 ArrayStack2 表示棧, 須要擴展功能 class ArrayStack2 { private int maxSize; // 棧的大小 private int[] stack; // 數組,數組模擬棧,數據就放在該數組 private int top = -1;// top表示棧頂,初始化爲-1 //構造器 public ArrayStack2(int maxSize) { this.maxSize = maxSize; stack = new int[this.maxSize]; } //增長一個方法,能夠返回當前棧頂的值, 可是不是真正的pop public int peek() { return stack[top]; } //棧滿 public boolean isFull() { return top == maxSize - 1; } //棧空 public boolean isEmpty() { return top == -1; } //入棧-push public void push(int value) { //先判斷棧是否滿 if(isFull()) { System.out.println("棧滿"); return; } top++; stack[top] = value; } //出棧-pop, 將棧頂的數據返回 public int pop() { //先判斷棧是否空 if(isEmpty()) { //拋出異常 throw new RuntimeException("棧空,沒有數據~"); } int value = stack[top]; top--; return value; } //顯示棧的狀況[遍歷棧], 遍歷時,須要從棧頂開始顯示數據 public void list() { if(isEmpty()) { System.out.println("棧空,沒有數據~~"); return; } //須要從棧頂開始顯示數據 for(int i = top; i >= 0 ; i--) { System.out.printf("stack[%d]=%d\n", i, stack[i]); } } //返回運算符的優先級,優先級是程序員來肯定, 優先級使用數字表示 //數字越大,則優先級就越高. public int priority(int oper) { if(oper == '*' || oper == '/'){ return 1; } else if (oper == '+' || oper == '-') { return 0; } else { return -1; // 假定目前的表達式只有 +, - , * , / } } //判斷是否是一個運算符 public boolean isOper(char val) { return val == '+' || val == '-' || val == '*' || val == '/'; } //計算方法 public int cal(int num1, int num2, int oper) { int res = 0; // res 用於存放計算的結果 switch (oper) { case '+': res = num1 + num2; break; case '-': res = num2 - num1;// 注意順序 break; case '*': res = num1 * num2; break; case '/': res = num2 / num1; break; default: break; } return res; } }