| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285 | 'use strict';/** * * @author Mai * @date * @version */;const zhBaseCalc = (function () {    const zeroPrecision = 12, mulPrecision = 12, divPrecision = 12;    function digitLength (num) {        // 兼容科学计数        var eSplit = num.toString().split(/[eE]/);        var len = (eSplit[0].split('.')[1] || '').length - (+(eSplit[1] || 0));        return len > 0 ? len : 0;    }    function powLength (num) {        var rs = num.toString();        if (rs.indexOf('+') > 0) {            return rs.match(/0*$/g).length();        } else {            const eSplit = rs.split(/[eE]/);            const len = Number(eSplit[1]) - this.digitLength(eSplit[0]);            return len > 0 ? len : 0;        }    }    function round (num, digit) {        return Math.round(num * Math.pow(10, digit)) / Math.pow(10, digit);    }    function add(num1, num2) {        var d1 = this.digitLength(num1), d2 = this.digitLength(num2);        return this.round(num1 + num2, Math.max(d1, d2));    }    function sub(num1, num2) {        var d1 = this.digitLength(num1), d2 = this.digitLength(num2);        return this.round(num1 - num2, Math.max(d1, d2));    }    function mul(num1, num2) {        return this.round(num1 * num2, mulPrecision);    }    function div(num1, num2) {        return this.round(num1 / num2, divPrecision);    }    function isNonZero(num) {        return num && round(num, zeroPrecision) !== 0;    }    return {        digitLength: digitLength,        powLength: powLength,        round: round,        add: add, sub: sub, mul: mul, div: div,        isNonZero: isNonZero,    }})();/** * 计算(四则、舍入) 统一,方便以后置换 * @type {{add, sub, mul, div, round}} */const ZhCalc = (function () {    Decimal.set({precision: 50, defaults: true});    /**     * 加法 num1 + num2     * @param num1     * @param num2     * @returns {number}     */    function add(num1, num2) {        //return zhBaseCalc.add(num1 ? num1 : 0, num2 ? num2: 0);        return num1 ? (num2 ? zhBaseCalc.add(num1, num2) : num1) : num2;    };    function sum(array) {        let result = 0;        for (const a of array) {            result = ZhCalc.add(result, a);        }        return result;    }    /**     * 减法 num1 - num2     * @param num1     * @param num2     * @returns {number}     */    function sub(num1, num2) {        return zhBaseCalc.sub(num1 ? num1 : 0, num2 ? num2 : 0);    }    /**     * 乘法 num1 * num2     * @param num1     * @param num2     * @returns {*}     */    function mul(num1, num2, digit = 6) {        //return Decimal.mul(num1 ? num1 : 0, num2 ? num2 : 0).toDecimalPlaces(digit).toNumber();        return (num1 && num2) ? (Decimal.mul(num1, num2).toDecimalPlaces(digit).toNumber()) : 0;    }    /**     * 除法 num1 / num2     * @param num1 - 被除数     * @param num2 - 除数     * @returns {*}     */    function div(num1, num2, digit = 6) {        if (num2 && !checkZero(num2)) {            //return Decimal.div(num1 ? num1: 0, num2).toDecimalPlaces(digit).toNumber();            return num1 ? (Decimal.div(num1, num2).toDecimalPlaces(digit).toNumber()) : 0;        } else {            return null;        }    }    /**     * 四舍五入     * @param {Number} value - 舍入的数字     * @param {Number} decimal - 要保留的小数位数     * @returns {*}     */    function round(value, decimal) {        decimal = decimal ? parseInt(decimal) : 0;        return value ? new Decimal(value).toDecimalPlaces(decimal).toNumber() : null;    }    const ExprCalc = {        /**         * 判断value是否是四则运算符         * @param {String} value - 判断字符串         * @return {Boolean}         */        isOperator(value) {            const operatorString = "+-*/()";            return operatorString.indexOf(value) > -1;        },        /**         * Rpn解析栈         * @param exp         * @returns {Array}         */        parse2Rpn(exp) {            const getPriority = function (value){                switch(value){                    case '+':                    case '-':                        return 1;                    case '*':                    case '/':                        return 2;                    default:                        return 0;                }            };            const priority = function (o1, o2){                return getPriority(o1) <= getPriority(o2);            };            const inputStack = [];            const outputStack = [];            const outputQueue = [];            for (let i = 0, len = exp.length; i < len; i++) {                const cur = exp[i];                if (cur !== ' ' ) {                    inputStack.push(cur);                }            }            let num = '', isNumPre = false, isOperatorPre = false;            while(inputStack.length > 0){                const cur = inputStack.shift();                if (this.isOperator(cur) && !(cur === '-' && !isNumPre)) {                    if (isNumPre) {                        outputQueue.push(parseFloat(num));                        num = '';                    }                    if (cur === '(') {                        outputStack.push(cur);                    } else if (cur === ')') {                        let po = outputStack.pop();                        while (po !== '(' && outputStack.length > 0) {                            outputQueue.push(po);                            po = outputStack.pop();                        }                        if (po !== '(') {                            throw "error: unmatched ()";                        }                    } else {                        while(priority(cur, outputStack[outputStack.length - 1]) && outputStack.length > 0){                            outputQueue.push(outputStack.pop());                        }                        outputStack.push(cur);                    }                    isNumPre = false;                    isOperatorPre = true;                } else {                    num = num + cur;                    isNumPre = true;                    isOperatorPre = false;                    if (inputStack.length === 0) {                        outputQueue.push(parseFloat(num));                    }                }            }            if (outputStack.length > 0) {                if (outputStack[outputStack.length - 1] === ')' || outputStack[outputStack.length - 1] === '(') {                    throw "error: unmatched ()";                }                while (outputStack.length > 0) {                    outputQueue.push(outputStack.pop());                }            }            return outputQueue;        },        /**         * 计算Rpn解析栈         * @param rpnQueue         * @returns {*}         */        evalRpn(rpnQueue) {            const getResult = function (num1, num2, opera) {                switch (opera) {                    case '+':                        return add(num1, num2);                    case '-':                        return sub(num1, num2);                    case '*':                        return mul(num1, num2, 10);                    case '/':                        return div(num1, num2, 10);                    default:                        throw '参数错误';                }            };            const outputStack = [];            while(rpnQueue.length > 0){                const cur = rpnQueue.shift();                if (!this.isOperator(cur)) {                    outputStack.push(cur);                } else {                    if (outputStack.length < 2) {                        throw "unvalid stack length";                    }                    const sec = outputStack.pop();                    const fir = outputStack.pop();                    outputStack.push(getResult(fir, sec, cur));                }            }            if (outputStack.length !== 1) {                throw "unvalid expression";            } else {                return outputStack[0];            }        },        /**         * 解析四则运算字符串并计算         * @param {String} expr         * @returns         */        calcExprStrRpn(expr) {            try {                if (!isNaN(Number(expr))) {                    return Number(expr);                } else {                    const rpnArr = this.parse2Rpn(expr);                    const result = this.evalRpn(rpnArr);                    return result === Infinity ? null : result;                }            } catch (err) {                return null;            }        },    };    return {add, sum, sub, mul, div, round, isNonZero: zhBaseCalc.isNonZero, calcExpr: ExprCalc}})();
 |