mofang-mopai-utils
Version:
Use it in Mopai system
186 lines (185 loc) • 7.47 kB
JavaScript
;
exports.__esModule = true;
/**
* A class for performing mathematical calculations on a given formula.
* 魔方魔派前端计算器
*/
var MofangMopaiCalculator = /** @class */ (function () {
/**
* Constructs a new instance of MfCalculator.
*
* @param {string} formula - The mathematical formula to be calculated.
* @throws Will throw an error if the formula is not provided or is not a string.
*/
function MofangMopaiCalculator(formula) {
if (!formula)
throw new Error('[传参错误] - 传入公式不能为空');
if (typeof formula !== 'string')
throw new Error('[传参错误] - 传入公式必须是字符串格式');
this._formula = formula.replace(/\s*/g, '');
}
/**
* Calculates the final result of the mathematical formula.
*
* @returns {number} The final result of the calculation.
*/
MofangMopaiCalculator.prototype.get = function () {
var res = this._splitFormula(this._formula);
return Number(res || 0);
};
/**
* Splits the mathematical formula into smaller parts for individual calculation.
* It continues to do this until there are no more operators left in the formula.
*
* @param {string} formula - The mathematical formula to be split.
* @returns {string} The final result of the calculation.
*
* @example
* _splitFormula('1.23+34.23+33-4-7.8*8.12+103.21') // returns '104.334'
*/
MofangMopaiCalculator.prototype._splitFormula = function (str) {
// 先乘除 后加减
var methodA = str.match(/\*|\//); // 判断有没有乘除法公式
var methodB = str.match(/\+|\-/); // 判断有没有加减法公式
// 如果未匹配到计算公式,则是计算后的最终结果,直接返回
if (!methodA && !methodB)
return str;
// 定义计算公式正则表达式
var reg;
if (methodA) {
reg = this._getRegExp(methodA[0]);
}
else if (methodB) {
reg = this._getRegExp(methodB[0]);
}
else {
throw new Error('[计算错误] - 未能成功获得计算公式正则表达式');
}
// 匹配字符串中的计算公式
var arr = str.match(reg);
var formula = (arr === null || arr === void 0 ? void 0 : arr[0]) || '';
if (!formula)
throw new Error('[计算错误] - 未匹配到计算公式');
// 对公式进行计算
var calculationResult = this._startCalc(formula);
// 把相应的计算公式替换成计算后的结果值
var replaceFormula = str.replace(formula, calculationResult.toString());
// 继续进行计算 直到字符串中没有计算公式为止
return this._splitFormula(replaceFormula);
};
/**
* Gets a regular expression based on the given calculation method.
*
* @param {string} method - The calculation method.
* @returns {RegExp} The regular expression.
*/
MofangMopaiCalculator.prototype._getRegExp = function (method) {
return new RegExp("\\d+(\\.\\d+)?\\".concat(method, "\\d+(\\.\\d+)?"));
};
/**
* Starts the calculation process for a given formula.
*
* @param {string} formula - The mathematical formula to be calculated.
* @returns {number} The result of the calculation.
*
* @example
* _startCalc('1.23+34.23') // returns 35.46
* _startCalc('34.23-33') // returns 1.23
* _startCalc('33*7.8') // returns 257.4
* _startCalc('103.21/8.12') // returns 12.699999999999998
*/
MofangMopaiCalculator.prototype._startCalc = function (formula) {
var _a;
if (!formula)
throw new Error('[计算错误] - 未找到需要计算的公式');
var reg = /\+|\-|\*|\//g;
var method = (_a = formula.match(reg)) === null || _a === void 0 ? void 0 : _a[0]; // 获取计算符
if (!method)
throw new Error('[计算错误] - 计算方法错误');
var numArray = formula.split(reg);
return this._execMath(numArray[0], numArray[1], method);
};
/**
* Executes a mathematical operation on two numbers.
*
* @param {number | string} [a=0] - The first number.
* @param {number | string} [b=0] - The second number.
* @param {string} method - The mathematical operation to be performed.
* @returns {number} The result of the mathematical operation.
* @throws Will throw an error if the method is not one of the following: '+', '-', '*', '/'.
*
* @example
* _execMath(1.23, 34.23, '+') // returns 35.46
* _execMath(34.23, 33, '-') // returns 1.23
* _execMath(33, 7.8, '*') // returns 257.4
* _execMath(103.21, 8.12, '/') // returns 12.699999999999998
*/
MofangMopaiCalculator.prototype._execMath = function (a, b, method) {
if (a === void 0) { a = 0; }
if (b === void 0) { b = 0; }
// 获取小数点后位数
var decimalLength = Math.max(this._getDecimalLength(a), this._getDecimalLength(b));
var x = this._transformToInteger(a, decimalLength); // 补位后的a值
var y = this._transformToInteger(b, decimalLength); // 补位后的b值
var z = Number(('1').padEnd(decimalLength + 1, '0')); // 补位数
switch (method) {
case '+': {
return (x + y) / z;
}
case '-': {
return (x - y) / z;
}
case '*': {
return x * y / Math.pow(z, 2);
}
case '/': {
return x / y;
}
default: {
return 0;
}
}
};
/**
* Gets the decimal length of a number.
*
* @param {number} num - The number to get the decimal length from.
* @returns {number} The decimal length of the number.
*
* @example
* _getDecimalLength(1.23) // returns 2
* _getDecimalLength(34.23) // returns 2
* _getDecimalLength(33) // returns 0
*/
MofangMopaiCalculator.prototype._getDecimalLength = function (num) {
var _a;
var n = num.toString();
var arr = n.split(/\./);
return ((_a = arr[1]) === null || _a === void 0 ? void 0 : _a.length) || 0;
};
/**
* Transforms a decimal number into an integer by padding the decimal part with zeros.
* !因为直接进位计算还是会出现小数点后无穷位的问题,所以直接用字符串进行格式化
*
* @param {number} num - The decimal number to be transformed.
* @param {number} offset - The number of decimal places to pad.
* @returns {number} The transformed integer.
*
* @example
* _transformToInteger(1.23, 2) // returns 123
* _transformToInteger(34.23, 3) // returns 34230
* _transformToInteger(33, 1) // returns 330
*/
MofangMopaiCalculator.prototype._transformToInteger = function (num, offset) {
var _a;
if (offset === 0)
return Number(num);
var n = num.toString();
var arr = n.split(/\./);
var dec = ((_a = arr[1]) === null || _a === void 0 ? void 0 : _a.toString()) || '0';
arr[1] = dec.padEnd(offset, '0');
return Number(arr.join(''));
};
return MofangMopaiCalculator;
}());
exports["default"] = MofangMopaiCalculator;