java String實現加,減,乘,除運算

分析過程

分析運算的幾種情況:

  • 帶有括號(不考慮大,小,中括號,統稱括號) 例如3*(2-1)
  • 帶負數,例如3+(-2)
  • 其他正常的情況

運算情況:

  • 運算符優先級考慮,這個很明顯,先“*”,“/”,再"+","-"最后是括號

計算不帶字符串的計算,我采用了2個棧來存放,一個棧存放符號,另一個存放數字,當存放符號時發現,當前的符號比棧頂得符號優先級低或者相等,就講棧中的數據進行計算。例如 a+b-c,按照正常順序,存放“-”是,數字棧中存放有a.b,而符號棧中存放有“+”,此時,進行判斷,發現“+”與“-”優先級相等,于是計算 a +b的值(假設a+b=d).計算后數字棧中將存放d,而符號棧將只存放"-".以此類推。

package com.example.cmcc.util;

import java.math.BigDecimal;
import java.util.Stack;

/**
 * <pre>
 *     author : lzy
 *     e-mail : zanyang.lin@newbeeair.com
 *     time   : 2017/05/16
 *     desc   :
 * </pre>
 */

public class StringCaculate {

    private Stack<BigDecimal> numbers = new Stack<BigDecimal>();

    private Stack<Character> chs = new Stack<Character>();

    /**
     * 比較當前操作符與棧頂元素操作符優先級,如果比棧頂元素優先級高,則返回true,否則返回false
     *
     * @param str 需要進行比較的字符
     * @return 比較結果 true代表比棧頂元素優先級高,false代表比棧頂元素優先級低
     */
    private boolean compare(char str) {
        if (chs.empty()) {
            // 當為空時,顯然 當前優先級最低,返回高
            return true;
        }
        char last = (char) chs.lastElement();
        switch (str) {
            case '*': {
                // '*/'優先級只比'+-'高
                if (last == '+' || last == '-')
                    return true;
                else
                    return false;
            }
            case '/': {
                if (last == '+' || last == '-')
                    return true;
                else
                    return false;
            }
            // '+-'為最低,一直返回false
            case '+':
                return false;
            case '-':
                return false;
        }
        return true;
    }

    public BigDecimal caculate(String st) {
        StringBuffer sb = new StringBuffer(st);
        StringBuffer num = new StringBuffer();
        String tem = null;
        char next;
        while (sb.length() > 0) {
            tem = sb.substring(0, 1);// 獲取字符串的第一個字符
            sb.delete(0, 1);
            if (isNum(tem.trim())) {
                num.append(tem);// 如果是數字,將其放入num當中
            } else {

                if (num.length() > 0 && !"".equals(num.toString().trim())) {// 當截取的字符不是數字時,則認為num中放置的時一個完整的數字,
                    // 如123+1,當獲取到+時,前面的123可以認為是一個完整的數
                    BigDecimal bd = new BigDecimal(num.toString().trim());
                    numbers.push(bd);
                    num.delete(0, num.length());
                }
                // 如果chs為空,這認為這時第一個字符直接放入
                if (!chs.isEmpty()) {
                    // 當當前的運算符優先級等于或者小于棧頂得預算符時,做運算.
                    // 例如,1+2+3,當截取到2,3之間的“+”與1,2之間的"+"優先級相等時,可以先計算1+2,使其變成3+3
                    // 同樣,1*2+3,當截取到2,3之間的“+”與1,2之間的"*"優先級小,可以先計算1*2,使其變成2+3

                    while (!compare(tem.charAt(0))) {
                        caculate();
                    }
                }
                // 當數字棧也為空時,既運算式的第一個數字為負數時
                if (numbers.isEmpty()) {
                    num.append(tem);
                } else {
                    chs.push(new Character(tem.charAt(0)));
                }
                // 判斷后一個字符是否為“-”號,為"-"號時,認為數字為負數
                // 例如 1*2*(-5),因為此運算不計算(),因此將被改寫為1*2*-5,如此情況,須將"-"認為是負數表達式而非減號
                next = sb.charAt(0);
                if (next == '-') {
                    num.append(next);
                    sb.delete(0, 1);
                }

            }
        }
        // 由于前面將數字放入棧時,是通過獲取符號為時處理,導致最后一個數字沒有放入棧中,因此將最后的數字放入棧中
        BigDecimal bd = new BigDecimal(num.toString().trim());
        numbers.push(bd);
        // 此時符號棧上最多只有2個符號,并且棧頂得符號優先級高,做運算
        while (!chs.isEmpty()) {
            caculate();
        }
        return numbers.pop();
    }


    BigDecimal result = null;// 運算結果

    private void caculate() {
        BigDecimal b = numbers.pop();// 第二個運算數
        BigDecimal a = null;// 第一個運算數
        a = numbers.pop();
        char ope = chs.pop();

        switch (ope) {
            // 如果是加號或者減號,則
            case '+':
                result = a.add(b);
                // 將操作結果放入操作數棧
                DebugLog.e(">>>>>>>>>>>>>" + result);
                numbers.push(result);
                break;
            case '-':
                // 將操作結果放入操作數棧
                result = a.subtract(b);
                DebugLog.e(">>>>>>>>>>>>>" + result);
                numbers.push(result);
                break;
            case '*':
                result = a.multiply(b);
                DebugLog.e(">>>>>>>>>>>>>" + result);
                // 將操作結果放入操作數棧
                numbers.push(result);
                break;
            case '/':
                result = a.divide(b);// 將操作結果放入操作數棧
                DebugLog.e(">>>>>>>>>>>>>" + result);
                numbers.push(result);
                break;
        }
    }

    public String getResult() {
        return result.toString();
    }

    private boolean isNum(String num) {
        return num.matches("[0-9]");
    }

    /**
     * 功能描述。
     * 解析,將帶有括號的運算符變成沒有帶括號的字運算
     */
    public BigDecimal parse(String st) {
        int start = 0;
        StringBuffer sts = new StringBuffer(st);
        int end = -1;
        while ((end = sts.indexOf(")")) > 0) {
            String s = sts.substring(start, end + 1);
            int first = s.lastIndexOf("(");
            BigDecimal value = caculate(sts.substring(first + 1, end));
            sts.replace(first, end + 1, value.toString());
        }
        DebugLog.e(">>>>>>>>>>>>>>>>>>>>" + sts.toString());
        return caculate(sts.toString());
    }

}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 表達式和運算符 程序中最簡單的表達式就是,程序中的常量 變量名也是一種簡單的表達式 復雜的表達式是由簡單的表達式組...
    zhaolion閱讀 1,672評論 3 12
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,779評論 18 399
  • 如果我當時沒有遇到你,或許就不會有莫名其妙的一見鐘情。 總是在青春正當回憶起從前的年少無知,然后感嘆自己輕狂得愚蠢...
    糯米mili閱讀 223評論 0 0
  • 設計app的第一件事就是確定設計風格。 主色主色是決定畫面風格趨向的顏色,主色可以是多種顏色。主色一般在logo和...
    jlnbda3488375閱讀 437評論 0 0
  • 你沒啥想說的哈,作業量還不是很多,嗯
    邱邱邱浩明閱讀 287評論 0 0