js实现输入数学公式和参数,计算结果
mathjs库和math-expression-evaluator库也可以实现
输入数学公式和参数,计算结果
class CalFormula {
constructor(formula, params) {
this.formula = formula
this.params = params
}
// 公式字符串转换成token数组(中缀表达式)
formulaToToken() {
// 匹配运算符和空格
const REG = /[()+\-/\*\^ ]/g;
const params = this.formula.split(REG).filter(Boolean)
const tokens = []
let tmpStr = this.formula.replace(/\s/g,'')
while (tmpStr.length > 0) {
if(tmpStr.startsWith(params[0])) {
tmpStr = tmpStr.replace(params[0], '')
tokens.push(params.shift())
} else {
tokens.push(tmpStr[0])
tmpStr = tmpStr.substring(1)
}
}
return tokens
}
// 中缀表达式转换成后缀表达式(逆波兰表达式)
toPostfix() {
const operatorRank = {
'(': 0,
')': 0,
'+': 1,
'-': 1,
'*': 2,
'/': 2,
'^': 3
};
const tokenList = this.formulaToToken()
const result = []
const operatorStack = []
for (const token of tokenList) {
// 如果是运算符
if(this.isOperator(token)) {
while (operatorStack.length > 0 && operatorRank[token] <= operatorRank[operatorStack[operatorStack.length - 1]]) {
const operator = operatorStack.pop()
result.push(operator)
}
operatorStack.push(token)
} else if (token === '(') {
operatorStack.push(token)
} else if (token === ')') {
while (operatorStack[operatorStack.length - 1] !== '(') {
const operator = operatorStack.pop()
result.push(operator)
}
operatorStack.pop()
} else {
result.push(token)
}
}
while (operatorStack.length > 0) {
result.push(operatorStack.pop())
}
return result
}
// 是否是运算符
isOperator(str) {
const operatorReg = /[+\-/\*\^]/;
return operatorReg.test(str)
}
// 运算符到实际操作映射
calculator(num1, num2, operator) {
const calculators = {
'+': (num1, num2) => (num1 + num2),
'-': (num1, num2) => (num1 - num2),
'*': (num1, num2) => (num1 * num2),
'/': (num1, num2) => (num1 / num2),
'^': (num1, num2) => (Math.pow(num1, num2))
}
return calculators[operator](num1, num2)
}
// 计算后缀表达式
calPostfix() {
console.log('rpn', this.toPostfix())
const tokenList = this.toPostfix()
const numarr = []
for (const token of tokenList) {
if (this.isOperator(token)) {
const num2 = numarr.pop()
const num1 = numarr.pop()
const res = this.calculator(num1, num2, token)
numarr.push(res)
} else {
numarr.push(this.params[token])
}
}
console.log(numarr[0])
return numarr[0]
}
}
const formula = '((a + b -c) * d / f) ^ g'
let params = {
a: 2,
b: 2,
c: 3,
d: 5,
f: 1,
g: 2,
h: 3,
}
new CalFormula(formula, params).calPostfix()