W72crm_web-master/node_modules/number-precision/build/index.es.js

153 lines
4.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @desc 解决浮动运算问题,避免小数点后产生多位数和计算精度损失。
*
* 问题示例2.3 + 2.4 = 4.6999999999999991.0 - 0.9 = 0.09999999999999998
*/
/**
* Correct the given number to specifying significant digits.
*
* @param num The input number
* @param precision An integer specifying the number of significant digits
*
* @example strip(0.09999999999999998) === 0.1 // true
*/
function strip(num, precision) {
if (precision === void 0) { precision = 15; }
return +parseFloat(Number(num).toPrecision(precision));
}
/**
* Return digits length of a number.
*
* @param num The input number
*/
function digitLength(num) {
// Get digit length of e
var eSplit = num.toString().split(/[eE]/);
var len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0);
return len > 0 ? len : 0;
}
/**
* Convert the given number to integer, support scientific notation.
* The number will be scale up if it is decimal.
*
* @param num The input number
*/
function float2Fixed(num) {
if (num.toString().indexOf('e') === -1) {
return Number(num.toString().replace('.', ''));
}
var dLen = digitLength(num);
return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num);
}
/**
* Log a warning if the given number is out of bounds.
*
* @param num The input number
*/
function checkBoundary(num) {
if (_boundaryCheckingState) {
if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {
console.warn(num + " is beyond boundary when transfer to integer, the results may not be accurate");
}
}
}
/**
* Create an operation to support rest params.
*
* @param operation The original operation
*/
function createOperation(operation) {
return function () {
var nums = [];
for (var _i = 0; _i < arguments.length; _i++) {
nums[_i] = arguments[_i];
}
var first = nums[0], others = nums.slice(1);
return others.reduce(function (prev, next) { return operation(prev, next); }, first);
};
}
/**
* Accurate multiplication.
*
* @param nums The numbers to multiply
*/
var times = createOperation(function (num1, num2) {
var num1Changed = float2Fixed(num1);
var num2Changed = float2Fixed(num2);
var baseNum = digitLength(num1) + digitLength(num2);
var leftValue = num1Changed * num2Changed;
checkBoundary(leftValue);
return leftValue / Math.pow(10, baseNum);
});
/**
* Accurate addition.
*
* @param nums The numbers to add
*/
var plus = createOperation(function (num1, num2) {
// 取最大的小数位
var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
// 把小数都转为整数然后再计算
return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;
});
/**
* Accurate subtraction.
*
* @param nums The numbers to subtract
*/
var minus = createOperation(function (num1, num2) {
var baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));
return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;
});
/**
* Accurate division.
*
* @param nums The numbers to divide
*/
var divide = createOperation(function (num1, num2) {
var num1Changed = float2Fixed(num1);
var num2Changed = float2Fixed(num2);
checkBoundary(num1Changed);
checkBoundary(num2Changed);
// fix: 类似 10 ** -4 为 0.00009999999999999999strip 修正
return times(num1Changed / num2Changed, strip(Math.pow(10, digitLength(num2) - digitLength(num1))));
});
/**
* Accurate rounding method.
*
* @param num The number to round
* @param decimal An integer specifying the decimal digits
*/
function round(num, decimal) {
var base = Math.pow(10, decimal);
var result = divide(Math.round(Math.abs(times(num, base))), base);
if (num < 0 && result !== 0) {
result = times(result, -1);
}
return result;
}
var _boundaryCheckingState = true;
/**
* Whether to check the bounds of number, default is enabled.
*
* @param flag The value to indicate whether is enabled
*/
function enableBoundaryChecking(flag) {
if (flag === void 0) { flag = true; }
_boundaryCheckingState = flag;
}
var index = {
strip: strip,
plus: plus,
minus: minus,
times: times,
divide: divide,
round: round,
digitLength: digitLength,
float2Fixed: float2Fixed,
enableBoundaryChecking: enableBoundaryChecking,
};
export { strip, plus, minus, times, divide, round, digitLength, float2Fixed, enableBoundaryChecking };
export default index;