java String實(shí)現(xiàn)加,減,乘,除運(yùn)算

分析過程

分析運(yùn)算的幾種情況:

  • 帶有括號(hào)(不考慮大,小,中括號(hào),統(tǒng)稱括號(hào)) 例如3*(2-1)
  • 帶負(fù)數(shù),例如3+(-2)
  • 其他正常的情況

運(yùn)算情況:

  • 運(yùn)算符優(yōu)先級(jí)考慮,這個(gè)很明顯,先“*”,“/”,再"+","-"最后是括號(hào)

計(jì)算不帶字符串的計(jì)算,我采用了2個(gè)棧來存放,一個(gè)棧存放符號(hào),另一個(gè)存放數(shù)字,當(dāng)存放符號(hào)時(shí)發(fā)現(xiàn),當(dāng)前的符號(hào)比棧頂?shù)梅?hào)優(yōu)先級(jí)低或者相等,就講棧中的數(shù)據(jù)進(jìn)行計(jì)算。例如 a+b-c,按照正常順序,存放“-”是,數(shù)字棧中存放有a.b,而符號(hào)棧中存放有“+”,此時(shí),進(jìn)行判斷,發(fā)現(xiàn)“+”與“-”優(yōu)先級(jí)相等,于是計(jì)算 a +b的值(假設(shè)a+b=d).計(jì)算后數(shù)字棧中將存放d,而符號(hào)棧將只存放"-".以此類推。

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>();

    /**
     * 比較當(dāng)前操作符與棧頂元素操作符優(yōu)先級(jí),如果比棧頂元素優(yōu)先級(jí)高,則返回true,否則返回false
     *
     * @param str 需要進(jìn)行比較的字符
     * @return 比較結(jié)果 true代表比棧頂元素優(yōu)先級(jí)高,false代表比棧頂元素優(yōu)先級(jí)低
     */
    private boolean compare(char str) {
        if (chs.empty()) {
            // 當(dāng)為空時(shí),顯然 當(dāng)前優(yōu)先級(jí)最低,返回高
            return true;
        }
        char last = (char) chs.lastElement();
        switch (str) {
            case '*': {
                // '*/'優(yōu)先級(jí)只比'+-'高
                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);// 獲取字符串的第一個(gè)字符
            sb.delete(0, 1);
            if (isNum(tem.trim())) {
                num.append(tem);// 如果是數(shù)字,將其放入num當(dāng)中
            } else {

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

                    while (!compare(tem.charAt(0))) {
                        caculate();
                    }
                }
                // 當(dāng)數(shù)字棧也為空時(shí),既運(yùn)算式的第一個(gè)數(shù)字為負(fù)數(shù)時(shí)
                if (numbers.isEmpty()) {
                    num.append(tem);
                } else {
                    chs.push(new Character(tem.charAt(0)));
                }
                // 判斷后一個(gè)字符是否為“-”號(hào),為"-"號(hào)時(shí),認(rèn)為數(shù)字為負(fù)數(shù)
                // 例如 1*2*(-5),因?yàn)榇诉\(yùn)算不計(jì)算(),因此將被改寫為1*2*-5,如此情況,須將"-"認(rèn)為是負(fù)數(shù)表達(dá)式而非減號(hào)
                next = sb.charAt(0);
                if (next == '-') {
                    num.append(next);
                    sb.delete(0, 1);
                }

            }
        }
        // 由于前面將數(shù)字放入棧時(shí),是通過獲取符號(hào)為時(shí)處理,導(dǎo)致最后一個(gè)數(shù)字沒有放入棧中,因此將最后的數(shù)字放入棧中
        BigDecimal bd = new BigDecimal(num.toString().trim());
        numbers.push(bd);
        // 此時(shí)符號(hào)棧上最多只有2個(gè)符號(hào),并且棧頂?shù)梅?hào)優(yōu)先級(jí)高,做運(yùn)算
        while (!chs.isEmpty()) {
            caculate();
        }
        return numbers.pop();
    }


    BigDecimal result = null;// 運(yùn)算結(jié)果

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

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

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

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

    /**
     * 功能描述。
     * 解析,將帶有括號(hào)的運(yùn)算符變成沒有帶括號(hào)的字運(yùn)算
     */
    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());
    }

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

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

友情鏈接更多精彩內(nèi)容