| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 | let _boundaryCheckingState = true; // 是否进行越界检查的全局开关/** * 把错误的数据转正 * @private * @example strip(0.09999999999999998)=0.1 */function strip(num, precision = 15) {  return +parseFloat(Number(num).toPrecision(precision));}/** * Return digits length of a number * @private * @param {*number} num Input number */function digitLength(num) {  // Get digit length of e  const eSplit = num.toString().split(/[eE]/);  const len = (eSplit[0].split('.')[1] || '').length - +(eSplit[1] || 0);  return len > 0 ? len : 0;}/** * 把小数转成整数,如果是小数则放大成整数 * @private * @param {*number} num 输入数 */function float2Fixed(num) {  if (num.toString().indexOf('e') === -1) {    return Number(num.toString().replace('.', ''));  }  const dLen = digitLength(num);  return dLen > 0 ? strip(Number(num) * Math.pow(10, dLen)) : Number(num);}/** * 检测数字是否越界,如果越界给出提示 * @private * @param {*number} num 输入数 */function checkBoundary(num) {  if (_boundaryCheckingState) {    if (num > Number.MAX_SAFE_INTEGER || num < Number.MIN_SAFE_INTEGER) {      console.warn(`${num} 超出了精度限制,结果可能不正确`);    }  }}/** * 把递归操作扁平迭代化 * @param {number[]} arr 要操作的数字数组 * @param {function} operation 迭代操作 * @private */function iteratorOperation(arr, operation) {  const [num1, num2, ...others] = arr;  let res = operation(num1, num2);  others.forEach((num) => {    res = operation(res, num);  });  return res;}/** * 高精度乘法 * @export */export function times(...nums) {  if (nums.length > 2) {    return iteratorOperation(nums, times);  }  const [num1, num2] = nums;  const num1Changed = float2Fixed(num1);  const num2Changed = float2Fixed(num2);  const baseNum = digitLength(num1) + digitLength(num2);  const leftValue = num1Changed * num2Changed;  checkBoundary(leftValue);  return leftValue / Math.pow(10, baseNum);}/** * 高精度加法 * @export */export function plus(...nums) {  if (nums.length > 2) {    return iteratorOperation(nums, plus);  }  const [num1, num2] = nums;  // 取最大的小数位  const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));  // 把小数都转为整数然后再计算  return (times(num1, baseNum) + times(num2, baseNum)) / baseNum;}/** * 高精度减法 * @export */export function minus(...nums) {  if (nums.length > 2) {    return iteratorOperation(nums, minus);  }  const [num1, num2] = nums;  const baseNum = Math.pow(10, Math.max(digitLength(num1), digitLength(num2)));  return (times(num1, baseNum) - times(num2, baseNum)) / baseNum;}/** * 高精度除法 * @export */export function divide(...nums) {  if (nums.length > 2) {    return iteratorOperation(nums, divide);  }  const [num1, num2] = nums;  const num1Changed = float2Fixed(num1);  const num2Changed = float2Fixed(num2);  checkBoundary(num1Changed);  checkBoundary(num2Changed);  // 重要,这里必须用strip进行修正  return times(    num1Changed / num2Changed,    strip(Math.pow(10, digitLength(num2) - digitLength(num1))),  );}/** * 四舍五入 * @export */export function round(num, ratio) {  const base = Math.pow(10, ratio);  let result = divide(Math.round(Math.abs(times(num, base))), base);  if (num < 0 && result !== 0) {    result = times(result, -1);  }  // 位数不足则补0  return result;}/** * 是否进行边界检查,默认开启 * @param flag 标记开关,true 为开启,false 为关闭,默认为 true * @export */export function enableBoundaryChecking(flag = true) {  _boundaryCheckingState = flag;}export default {  times,  plus,  minus,  divide,  round,  enableBoundaryChecking,};
 |