加减乘除运算

原创 无尾熊 随笔 随意 60阅读 28 天前 举报

备注: 需要引入balanced-match.js 用来拆括号的

    // 计算公式:a+b*(c+d) 支持加、减、乘、除、括号
    // 拆括号
    function mapExpr (matchItem, callback) {
        matchItem = balanced('(', ')', matchItem);
        if (callback) callback(matchItem);
        if ( balanced('(', ')', matchItem.body)) {
            mapExpr(matchItem.body, callback);
        }
    }
    function removeBracket(formula) {
        let result = {variate: null};
        let matchItem = balanced('(', ')', formula);
        if (matchItem) {
            while (matchItem) {
                formula = matchItem.pre + `variate${Object.keys(result).length}` + matchItem.post;
                result['variate'] = formula;
                result[`variate${Object.keys(result).length}`] = matchItem.body;
                if (balanced('(', ')', matchItem.body)) {
                    matchItem = mapExpr(matchItem.body, (item) => {
                        result[`variate${Object.keys(result).length - 1}`] = item.pre + `variate${Object.keys(result).length}` + item.post;
                        result[`variate${Object.keys(result).length}`] = item.body;
                    });
                    if (!matchItem) {
                        matchItem = balanced('(', ')', formula);
                    }
                } else {
                    matchItem = balanced('(', ')', formula);
                }
            }
        } else {
            result['variate'] = matchItem;
        }
        return result;
    }
    // 按照加减乘除拆开
    function splitExpr(expr) {
        return expr.split(/([+|\-|*|\/])/g)
    }
    // 判断是否是符号
    function isSymbol(value) {
        return '+-*/'.indexOf(value) > -1
    }
    // 加减乘除优先级
    function  getPriority(symbol) {
        switch (symbol) {
            case '+':
            case '-':
                return 1;
            case '*':
            case '/':
                return 2;
            default:
                return 0;
        }
    }
    function priority(p1, p2) {
        return getPriority(p1) <= getPriority(p2);
    }
    // 按照优先级重排表达式
    function resetExpr (expr) {
        let inputExpr = splitExpr(expr);
        // ["1", "+", "2", "*", "3"]
        let outExpr = [];
        let outSymbol = [];
        for (let i = 0; i < inputExpr.length; i++) {
            let item = inputExpr[i];
            if (isSymbol(item)) {
                while(outSymbol.length > 0 && priority(item, outSymbol[outSymbol.length - 1])) {
                    outExpr.push(outSymbol.pop())
                }
                outSymbol.push(item)
            } else {
                outExpr.push(item)
            }
        }
        while (outSymbol.length > 0) {
            outExpr.push(outSymbol.pop())
        }
        return outExpr;
    }
    // 加减乘除
    function arithmetic(a1, a2, symbol){
        a1 = new Number(a1);
        a2 = new Number(a2);
        switch (symbol) {
            case '+':
                return a1 + a2;
                break;
            case '-':
                return a1 - a2;
                break;
            case '*':
                return a1 * a2;
                break;
            case '/':
                return a1 / a2;
                break;
        }
    }
    //不带括号的加减乘除计算
    function calculate(expr) {
        let inputExpr = resetExpr(expr);
        let outExpr = [];
        for (let i = 0; i < inputExpr.length; i++) {
            let item = inputExpr[i];
            if (isSymbol(item)) {
                if (outExpr.length < 2) {
                    return undefined;
                }
                let a1 = outExpr.pop();
                let a2 = outExpr.pop();
                outExpr.push(arithmetic(a2, a1, item))
            } else {
                outExpr.push(item)
            }
        }
        if (outExpr.length > 1) {
            return undefined;
        } else {
            return outExpr[0];
        }
    }
    // 计算带括号的 1+2*(8-4)-8/2
    function getResult (expr) {
        let result = null;
        let exprJson = null;
        if (removeBracket(expr)) {
            exprJson = removeBracket(expr);
        } else {
            return
        }
        if (exprJson === 'error') return;
        const keys = Object.keys(exprJson);
        for (let i = keys.length - 1; i >= 0; i--){
            const storage = calculate(exprJson[keys[i]]);
            if (!storage) {
                result = NaN;
                return result;
            }
            if (i !==0) {
                exprJson[keys[i]] = storage;
                exprJson[keys[0]] = exprJson[keys[0]].replace(keys[i], exprJson[keys[i]]);
                exprJson[keys[i-1]] = exprJson[keys[i-1]].replace(keys[i], exprJson[keys[i]]);
            } else {
                result = storage;
            }
        }
        return result;
    }
    // 保留小数
    function fixed (num, fixed) {
        if (!num || isNaN(num)) {
            return null;
        }
        return Math.round(num * Math.pow(10, fixed)) / Math.pow(10, fixed)
    }
    const result = getResult('1+2*(8-4/(5-3*(2-1)))-2*(3-1/(4-1))');
    console.log(fixed(result, 3))
评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复