简单四则运算及表达式校验和转换工具类,仅供参考。
完整工具类请往我的github项目bee.js
//简单四则运算
ElementaryArithmeticUtils = {
//运算符优先级
operatorPrecedence: {
'+': 0,
'-': 0,
'*': 1,
'×': 1,
'÷': 1,
'\/': 1
},
//运算符
operator: {
'+': '+',
'-': '-',
'*': '*',
'×': '*',
'÷': '/',
'\/': '/'
},
//加法
add: function(operandLeft, operandRight) {
var operand1 = operandLeft.toString();
var operand2 = operandRight.toString();
var decimalPlace1 = operand1.indexOf('.') >= 0 ? operand1.split('.')[1].length : 0;
var decimalPlace2 = operand2.indexOf('.') >= 0 ? operand2.split('.')[1].length : 0;
var multiple = Math.pow(10, Math.max(decimalPlace1, decimalPlace2));
return(operandLeft * multiple + operandRight * multiple) / multiple;
},
//减法
subtract: function(operandLeft, operandRight) {
var operand1 = operandLeft.toString();
var operand2 = operandRight.toString();
var decimalPlace1 = operand1.indexOf('.') >= 0 ? operand1.split('.')[1].length : 0;
var decimalPlace2 = operand2.indexOf('.') >= 0 ? operand2.split('.')[1].length : 0;
var multiple = Math.pow(10, Math.max(decimalPlace1, decimalPlace2));
//toFixed避免多出来小数位,如 11.3-10.12000=1.1800000000000015
var decimalPlace = (decimalPlace1 >= decimalPlace2) ? decimalPlace1 : decimalPlace2;
return((operandLeft * multiple - operandRight * multiple) / multiple).toFixed(decimalPlace);
},
//乘法
multiply: function(operandLeft, operandRight) {
var operand1 = operandLeft.toString();
var operand2 = operandRight.toString();
var decimalPlace1 = operand1.indexOf('.') >= 0 ? operand1.split('.')[1].length : 0;
var decimalPlace2 = operand2.indexOf('.') >= 0 ? operand2.split('.')[1].length : 0;
var multiple1 = Math.pow(10, decimalPlace1);
var multiple2 = Math.pow(10, decimalPlace2);
return((operandLeft * multiple1) * (operandRight * multiple2)) / Math.pow(10, decimalPlace1 + decimalPlace2);
},
//除法
divide: function(operandLeft, operandRight) {
var operand1 = operandLeft.toString();
var operand2 = operandRight.toString();
var decimalPlace1 = operand1.indexOf('.') >= 0 ? operand1.split('.')[1].length : 0;
var decimalPlace2 = operand2.indexOf('.') >= 0 ? operand2.split('.')[1].length : 0;
var multiple1 = Math.pow(10, decimalPlace1);
var multiple2 = Math.pow(10, decimalPlace2);
return((operandLeft * multiple1) / (operandRight * multiple2)) * Math.pow(10, decimalPlace2 - decimalPlace1);
},
//校验表达式的合法性
isArithmeticExpression: function(expression) {
try {
expression = expression.replace(/÷/g, '/').replace(/×/g, '*');
var result = eval(expression);
} catch(e) {
return false;
}
return true;
},
//计算
calculate: function(expression) {
var value = eval(expression);
return value;
},
//中缀表达式转后缀表达式
infixToPostfixExpression: function(expression) {
expression = Bee.StringUtils.deleteWhitespace(expression);
expression = this.eliminatePositiveOrNegativeSign(expression);
var operatorStack = [];
var resultStack = [];
var elementArr = expression.match(/[-+\/÷*×()]|(?:[1-9]\d*|0)(?:\.\d+)?/g);
var size = elementArr.length;
for(var i = 0; i < size; i++) {
if(Bee.StringUtils.isNumeric(elementArr[i])) {
//如果是数值
resultStack.push(elementArr[i]);
} else {
//操作符栈顶元素
var operatorStackTopElement = operatorStack.length === 0 ? '' : operatorStack[operatorStack.length - 1];
//运算符
if(operatorStack.length === 0 || elementArr[i] === '(' || operatorStackTopElement === '(' || this.operatorPrecedence[elementArr[i]] > this.operatorPrecedence[operatorStackTopElement]) {
//操作符栈为空或栈顶元素为右括号')',或操作符的优先级比栈顶运算符高或相等,直接入栈
operatorStack.push(elementArr[i]);
} else {
//如果是右括号")",则依次弹出操作符栈顶的运算符,并压入结果栈,直到遇到左括号'('为止,左右括号不压入结果栈;
if(elementArr[i] === ')') {
for(var index = operatorStack.length - 1; index >= 0; index--) {
if(operatorStack[index] === '(') {
operatorStack.pop();
break;
} else {
resultStack.push(operatorStack.pop());
}
}
} else {
//将符号栈顶的运算符弹出并压入到结果栈中,再次与符号栈中新的栈顶运算符相比较
resultStack.push(operatorStack.pop());
i--;
continue;
}
}
}
}
//处理操作符栈剩余的符号
if(operatorStack.length > 0) {
for(var j = operatorStack.length - 1; j >= 0; j--) {
resultStack.push(operatorStack.pop());
}
}
//结果返回
return resultStack.join(' ');
},
//中缀表达式转前缀表达式(结果以空格隔开)
infixToPrefixExpression: function(expression) {
expression = Bee.StringUtils.deleteWhitespace(expression);
expression = this.eliminatePositiveOrNegativeSign(expression);
var operatorStack = [];
var resultStack = [];
var elementArr = expression.match(/[-+\/÷*×()]|(?:[1-9]\d*|0)(?:\.\d+)?/g);
var size = elementArr.length;
for(var i = size - 1; i >= 0; i--) {
if(Bee.StringUtils.isNumeric(elementArr[i])) {
//如果是数值
resultStack.push(elementArr[i]);
} else {
//操作符栈顶元素
var operatorStackTopElement = operatorStack.length === 0 ? '' : operatorStack[operatorStack.length - 1];
//运算符
if(operatorStack.length === 0 || elementArr[i] === ')' || operatorStackTopElement === ')' || this.operatorPrecedence[elementArr[i]] >= this.operatorPrecedence[operatorStackTopElement]) {
//操作符栈为空或栈顶元素为右括号')',或操作符的优先级比栈顶运算符高或相等,直接入栈
operatorStack.push(elementArr[i]);
} else {
//如果是左括号"(",则依次弹出操作符栈顶的运算符,并压入结果栈,直到遇到右括号')'为止,左右括号不压入结果栈;
if(elementArr[i] === '(') {
for(var index = operatorStack.length - 1; index >= 0; index--) {
if(operatorStack[index] === ')') {
operatorStack.pop();
break;
} else {
resultStack.push(operatorStack.pop());
}
}
} else {
//将符号栈顶的运算符弹出并压入到结果栈中,再次与符号栈中新的栈顶运算符相比较
resultStack.push(operatorStack.pop());
i++;
continue;
}
}
}
}
//处理操作符栈剩余的符号
if(operatorStack.length > 0) {
for(var j = operatorStack.length - 1; j >= 0; j--) {
resultStack.push(operatorStack.pop());
}
}
//结果返回
return resultStack.reverse().join(' ');
},
//解决正负号问题-1转为0-1;+1转为0+1
eliminatePositiveOrNegativeSign: function(expression) {
return expression.replace(/(\(|^)([-+])/g, '$10$2');
},
//把中缀表达式转为前缀表达式,再计算
calculateByPrefixExpression: function(expression) {
var elementArr = this.infixToPrefixExpression(expression).split(' ');
var size = elementArr.length;
var resultStack = [];
for(var i = size - 1; i >= 0; i--) {
if(Bee.StringUtils.isNumeric(elementArr[i])) {
//如果是数值
resultStack.push(elementArr[i]);
} else {
var operand1 = resultStack.pop();
var operand2 = resultStack.pop();
var result;
switch(elementArr[i]) {
case '+':
result = Bee.ElementaryArithmeticUtils.add(operand1, operand2);
break;
case '-':
result = Bee.ElementaryArithmeticUtils.subtract(operand1, operand2);
break;
case '×':
case '*':
result = Bee.ElementaryArithmeticUtils.multiply(operand1, operand2);
break;
case '\/':
case '÷':
result = Bee.ElementaryArithmeticUtils.divide(operand1, operand2);
break;
default:
result = '';
alert("The operator 【" + elementArr[i] + "】 is not legal");
break;
}
resultStack.push(result);
}
}
return resultStack;
},
//把中缀表达式转为后缀表达式,再计算
calculateByPostfixExpression: function(expression) {
var elementArr = this.infixToPostfixExpression(expression).split(' ');
var size = elementArr.length;
var resultStack = [];
for(var i = 0; i < size; i++) {
if(Bee.StringUtils.isNumeric(elementArr[i])) {
//如果是数值
resultStack.push(elementArr[i]);
} else {
var operand1 = resultStack.pop();
var operand2 = resultStack.pop();
var result;
switch(elementArr[i]) {
case '+':
result = Bee.ElementaryArithmeticUtils.add(operand2, operand1);
break;
case '-':
result = Bee.ElementaryArithmeticUtils.subtract(operand2, operand1);
break;
case '×':
case '*':
result = Bee.ElementaryArithmeticUtils.multiply(operand2, operand1);
break;
case '\/':
case '÷':
result = Bee.ElementaryArithmeticUtils.divide(operand2, operand1);
break;
default:
result = '';
alert("The operator 【" + elementArr[i] + "】 is not legal");
break;
}
resultStack.push(result);
}
}
return resultStack;
},
//横式计算
horizontalCalculation: function(expression) {
expression = Bee.StringUtils.deleteWhitespace(expression);
expression = this.eliminatePositiveOrNegativeSign(expression);
var result = expression;
while(expression.indexOf('(') >= 0) {
expression = expression.replace(/\([^()]+\)/g, function(matchStr) {
return eval(matchStr);
});
result += '=' + expression;
}
while(expression.indexOf('[') >= 0) {
expression = expression.replace(/\[[^\[\]]+\]/g, function(matchStr) {
return eval(matchStr);
});
result += '=' + expression;
}
while(expression.indexOf('{') >= 0) {
expression = expression.replace(/\{[^{}]+\}/g, function(matchStr) {
return eval(matchStr);
});
result += '=' + expression;
}
var pattern = /(?:[1-9]\d*|0)(?:\.\d+)?[*/](?:[1-9]\d*|0)(?:\.\d+)?/;
while(expression.indexOf('*') >= 0 || expression.indexOf('/') >= 0) {
expression = expression.replace(pattern, function(matchStr, index) {
return eval(matchStr);
});
result += '=' + expression;
}
if(/[-+*/]/.test(expression)) {
result += '=' + eval(expression);
}
return result;
},
//竖式计算
verticalCalculation: function(expression) {
var result = this.horizontalCalculation(expression);
return result.replace(/=/g, "\n$&");
}
};