JS 模拟计算机计算方式(含有防丢失精度方法)
输入公式字符串,自动计算出结果,支持加减乘除、括号、幂函数
export {
compute,
add,
cut,
multiple,
divide,
}
function compute(str) {
let temp = '';
let arr = [];
if (str[0] === '-') {
temp = '-';
str = str.substring(1);
}
for (let i = 0; i < str.length; i++) {
if (str[i] === '-' && isNaN(str[i - 1])) {
temp += str[i];
continue;
}
if (isNaN(str[i]) && str[i] !== '.') {
if (temp) { arr.push(temp); }
arr.push(str[i]);
temp = '';
continue;
}
temp += str[i];
}
if (temp) { arr.push(temp); }
return computeByBrackets(arr);
}
function computeByBrackets(arr) {
while(true) {
let computeArr = [];
let index = arr.indexOf('(');
if (index === -1) { break; }
let lastIndex = findLastIndex(arr, index, index);
for (let i = index + 1; i < lastIndex; i++) {
computeArr.push(arr[i]);
}
let result;
if (computeArr.indexOf('(') !== -1) {
result = computeByBrackets(computeArr);
} else {
result = computeResult(computeArr);
}
arr.splice(index, lastIndex - index + 1, result);
}
return computeResult(arr);
}
function computeResult(arr) {
let index = 1;
let result = 0;
if (arr.length === 3) {
return SingleCalc(arr[index], arr[index - 1], arr[index + 1]);
}
let power = arr.indexOf('^');
if (power !== -1) {
index = power;
result = SingleCalc(arr[index], arr[index - 1], arr[index + 1]);
arr.splice(index - 1, 3, result);
return computeResult(arr);
}
let mult = arr.indexOf('*');
let div = arr.indexOf('/');
if (mult !== -1 && div !== -1) {
index = mult < div ? mult : div;
result = SingleCalc(arr[index], arr[index - 1], arr[index + 1]);
arr.splice(index - 1, 3, result);
return computeResult(arr);
}
if (mult !== -1) {
index = mult;
result = SingleCalc(arr[index], arr[index - 1], arr[index + 1]);
arr.splice(index - 1, 3, result);
return computeResult(arr);
}
if (div !== -1) {
index = div;
result = SingleCalc(arr[index], arr[index - 1], arr[index + 1]);
arr.splice(index - 1, 3, result);
return computeResult(arr);
}
result = SingleCalc(arr[index], arr[index - 1], arr[index + 1]);
arr.splice(index - 1, 3, result);
return computeResult(arr);
}
function SingleCalc(c,a,b){
switch(c) {
case '+': return add(a, b);
case '-': return cut(a, b);
case '*': return multiple(a, b);
case '/': return divide(a, b);
case '^': return Math.pow(Number(a), Number(b));
default: return NaN;
}
}
function findLastIndex(arr, index, lastIndex) {
let last = arr.indexOf(')', lastIndex + 1);
let first = arr.indexOf('(', index + 1);
if (first === -1 || first > last) { return last; }
if (first < last) { return findLastIndex(arr, first, last); }
}
function add(arg1, arg2) {
let r1, r2, m, s1 = arg1.toString(), s2 = arg2.toString();
let sArr = s1.split('.');
r1 = sArr[1] ? sArr[1].length : 0;
sArr = s2.split('.');
r2 = sArr[1] ? sArr[1].length : 0;
m = Math.pow(10, Math.max(r1, r2));
return (arg1 * m + arg2 * m) / m;
}
function cut(arg1, arg2) {
let r1, r2, m, n, s1 = arg1.toString(), s2 = arg2.toString();
let sArr = s1.split('.');
r1 = sArr[1] ? sArr[1].length : 0;
sArr = s2.split('.');
r2 = sArr[1] ? sArr[1].length : 0;
m = Math.pow(10, Math.max(r1, r2));
n = (r1 >= r2) ? r1 : r2;
let result = ((arg1 * m - arg2 * m) / m).toFixed(n);
return Number(result);
}
function multiple(arg1, arg2) {
if (!arg1 || !arg2) { return 0; }
let m = 0, s1 = arg1.toString(), s2 = arg2.toString();
let sArr = s1.split('.');
m += sArr[1] ? sArr[1].length : 0;
sArr = s2.split('.');
m += sArr[1] ? sArr[1].length : 0;
return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
}
function divide(arg1, arg2) {
let t1 = 0, t2 = 0, r1, r2, s1 = arg1.toString(), s2 = arg2.toString();
if (s2 === '0') {
return 0;
}
let sArr = s1.split('.');
t1 = sArr[1] ? sArr[1].length : 0;
sArr = s2.split('.');
t2 = sArr[1] ? sArr[1].length : 0;
r1 = Number(s1.replace(".", ""));
r2 = Number(s2.replace(".", ""));
return (r1 / r2) * Math.pow(10, t2 - t1);
}