已上传到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;