解决直接计算会精度丢失的问题,
import Decimal from 'decimal.js';
import _ from 'lodash';
export const thousandBitSeparator=(num)=> {
return num && num
.toString()
.replace(/(\d)(?=(\d{3})+\.)/g, function($0, $1) {
return $1 + ",";
});
}
// 计算器
// str 即为input输入的数据
function sliceCountStr(str) {
const arr: string[] = []; // 记录分割计算表达式
for (let i = 0; i < str.length; i++) {
const item = str.charAt(i);
if(item === ' ') continue
let num = item;
if (/[\d|\.]/.test(item)) {
let j = i + 1;
for (; j < str.length; j++) {
const otherItem = str.charAt(j);
if (!/[\d|\.]/.test(otherItem)) {
break;
}
}
num = str.slice(i, j);
i = j - 1;
num = +num;
}
arr.push(num);
}
return arr;
}
// arr 即为上一步处理好的数组
export function countHandle(formula) {
const arr = sliceCountStr(formula);
const charArr: string[] = [];
const numArr: string[] = [];
for (let i = 0; i < arr.length; i++) {
if (_.isNumber(arr[i])) {
numArr.push(arr[i]);
} else {
if (charArr.length) {
// 步骤1
// 如果当前的运算符的优先级比栈顶的优先级低或相等,就说明需要把前面的值全部计算好
// 存储运算符的栈要一直出栈,直到栈为空或当前的字符的优先级比栈顶的优先级高
while (isPop(arr[i], charArr[charArr.length - 1])) {
const t2 = numArr.pop();
const t1 = numArr.pop();
const char = charArr.pop();
handleCalculation(numArr, t1, t2, char);
}
// 当前运算符为右括号
if (arr[i] === ')') {
// 取栈顶运算符
let st: string | undefined = charArr[charArr.length - 1];
// 步骤2
// 遇到右括号也要一直出栈,直到遇到左括号
while (st !== '(') {
let t1;
let t2;
const char = charArr.pop();
if (char !== '(') {
t2 = numArr.pop();
t1 = numArr.pop();
handleCalculation(numArr, t1, t2, char);
}
st = char;
}
}
// 运算符不为右括号
if (arr[i] !== ')') {
charArr.push(arr[i]);
}
} else {
// 步骤3
// 运算符栈为空,直接入栈
charArr.push(arr[i]);
}
}
}
// 步骤4
// 最后运算符栈如果还有字符,要一直出栈直到为空
while (charArr.length) {
const t2 = numArr.pop();
const t1 = numArr.pop();
const char = charArr.pop();
handleCalculation(numArr, t1, t2, char);
}
return numArr[0];
}
// 基本加减乘除运算处理
function handleCalculation(numArr, num1, num2, char) {
const _num1 = new Decimal(num1);
let result;
switch (char) {
case '+':
result = _num1.plus(num2);
break;
case '-':
result = _num1.minus(num2);
break;
case '*':
result = _num1.times(num2);
break;
case '/':
result = _num1.div(num2);
break;
default: console.error('运算符错误',char);
break;
}
result && numArr.push(result.toFixed(2));
}
// 判断运算符的优先级,是否出栈进行计算
function isPop(char1, char2) {
// 运算符栈为空
if (!char2) {
return false;
}
// 运算符优先级相同
if (['+', '-'].includes(char1) && ['+', '-'].includes(char2)) {
return true;
}
// 前者运算符优先级比后者低
if (['+', '-'].includes(char1) && ['*', '/'].includes(char2)) {
return true;
}
// 运算符优先级相同
if (['*', '/'].includes(char1) && ['*', '/'].includes(char2)) {
return true;
}
// 前者运算符优先级比后者高
if (['*', '/'].includes(char1) && ['+', '-'].includes(char2)) {
return false;
}
}