bug
jiangping
2023-11-07 64b432916af9c9218ab3f3eca614e26c542142ae
minipro_standard/uni_modules/uview-ui/libs/function/digit.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,167 @@
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,
};