zoukankan      html  css  js  c++  java
  • js解析数学运算公式

    
    

    已上传到npm,NPM包地址:

    https://www.npmjs.com/package/exec-mathexpress

    //运行demo

    const execMathExpress=require('./utils/execMathExpress');

    //贝叶斯 条件概率公式 SW=WS*S/(WS*S+WH*H);(只用于二分类)
    console.log(execMathExpress('WS*S/(WS*S+WH*H)',{
    WS:'1/2',
    S:'1/4',
    WH:'1/2',
    H:'3/4'
    }))
    //->Fraction { num: 1, den: 4 }

    //贝叶斯联合概率公式(只用于二分类)
    console.log(execMathExpress('P0*P1*P2/(P0*P1*P2+(1-P0)*(1-P1)*(1-P2))',{ P0: '1/2', P1: '2/3', P2: '3/4' }))
    //->Fraction { num: 6, den: 7 }


    源码:execMathExpress.js
    //欧几里得算法 求两个数a、b的最大公约数
    function gcd(a,b){
        return b===0?a:gcd(b,a%b)
    }
    //分数类 分子,分母
    class Fraction{
        static create(num,den=1) {
            if(num instanceof Fraction){
                return num;
            }else if(/(-?d+)/(d+)/.test(num)){
                return new Fraction(parseInt(RegExp.$1),parseInt(RegExp.$2))
            }else{
                if(/.(d+)/.test(num)){
                    num=num*Math.pow(10,RegExp.$1.length);
                    den=den*Math.pow(10,RegExp.$1.length);
                }
                if(/.(d+)/.test(den)){
                    num=num*Math.pow(10,RegExp.$1.length);
                    den=den*Math.pow(10,RegExp.$1.length);
                }
                return new Fraction(num,den)
            }
        }
        constructor(num=0,den=1){
            if(den<0){
                num=-num;
                den=-den;
            }
            if(den===0){
                throw '分母不能为0'
            }
            let g=gcd(Math.abs(num),den)
            this.num=num/g;
            this.den=den/g;
        }
        //
        add(o){
            return new Fraction(this.num*o.den+this.den*o.num,this.den*o.den)
        }
        //
        sub(o){
            return new Fraction(this.num*o.den-this.den*o.num,this.den*o.den)
        }
        //
        multiply(o){
            return new Fraction(this.num*o.num,this.den*o.den);
        }
        //
        divide(o){
            return new Fraction(this.num*o.den,this.den*o.num);
        }
        //小于
        lessThan(o){
            return this.num*o.den<this.den*o.num;
        }
        //等于
        equal(o){
            return this.num*o.den===this.den*o.num;
        }
        toString() {
            return this.num+'/'+this.den;
        }
    }
    
    //解析数学表达式
    function execMathExpress(formula,obj){
        //局部变量
        const tempObj=Object.assign({
            _0:0
        },obj);
        //计算缓存
        const keyCache={};
        let index=1;
    
        formula=formula.replace(/ /g,'');//清理空格
        //解析数字
        formula=formula.replace(/(^|[(*+/-])(d+.d+|d+)/g,function (m,p1,p2) {
            if(keyCache[p2]){
                return p1+keyCache[p2];
            }
            const key=keyCache[p2]='_'+index++;
            tempObj[key]=Fraction.create(p2);
            return p1+key;
        })
    
        function getKey(p1,p2,p3) {
            const keyC=p1+p2+p3;
            if(keyCache[keyC]){
                return keyCache[keyC];
            }
            const key=keyCache[keyC]='_'+index++;
            const fA=Fraction.create(tempObj[p1])
            const fB=Fraction.create(tempObj[p3])
            if(p2==='*'){
                tempObj[key]=fA.multiply(fB);
            }else if(p2==='/'){
                tempObj[key]=fA.divide(fB);
            }else if(p2==='+'){
                tempObj[key]=fA.add(fB);
            }else if(p2==='-'){
                tempObj[key]=fA.sub(fB);
            }
            return key;
        }
        function run(s) {
    
            //子表达式
            if(/(([^(]+?))/.test(s)){
                s=s.replace(/(([^(]+?))/g,function (m,p1,p2) {
                    return run(p1);
                })
            }
            //负号
            s=s.replace(/([*/+]|^)-(w+)/g,function (m,p1,p2) {
                return getKey('_0','-',p2);
            })
            //返回
            if(/(^w+$)/.test(s)){
                return RegExp.$1;
            }
            //乘法、除法、加法、减法
            const expArr=['*','/','+','-'];
            for(let i=0;i<expArr.length;i++){
                const p=expArr[i];
                const reg=new RegExp('(\w+)['+p+'](\w+)');
                while (reg.test(s)){
                    s=s.replace(reg,function (m,p1,p2) {
                        return getKey(p1,p,p2);
                    })
                }
            }
            //返回
            if(/(^w+$)/.test(s)){
                return RegExp.$1;
            }
            return run(s);
        }
        return tempObj[run(formula)]
    }
    module.exports=execMathExpress;
  • 相关阅读:
    剑指 Offer 43. 1~n整数中1出现的次数
    剑指 Offer 54. 二叉搜索树的第k大节点(递归)
    第三个JSP作业
    第二个JSP作业-用循环结构输出三行五列的table
    第二个JSP作业-编写jsp页面,输出大写、小写英文字母表
    第一个JSP作业
    安卓课设
    第十次作业
    第八次作业
    第九次作业
  • 原文地址:https://www.cnblogs.com/caoke/p/11053253.html
Copyright © 2011-2022 走看看