常用工具类方法记录

192 阅读2分钟

1.浮动运算

解决浮动运算问题,避免小数点后产生多位数和计算精度损失。

1.1 获取当前数小数位的长度

// 获取当前数小数位的长度(处理科学计数法,本质上处理e-n的情况)
function digitLength(num) {
  const eSplit = num.toString().split(/[eE]/);
  const len = (eSplit[0].split('.')[1] || '').length - (+eSplit[1] || 0);
  return len > 0 ? len : 0;
}

1.2 把小数转成整数

// 把小数转成整数,支持科学计数法。如果是小数则放大成整数
function float2Fixed(num) {
  if (+num.toString().indexOf('e')) {
    return Number(num.toString().replace('.', ''));
  }
  const dlen = digitLength(num);
  return dlen > 0 ? num * (window as any).Math.pow(10, dlen) : num;
}

1.3 精确乘法

function multiply(...others: number[]) {
  if (others.length > 1) {
    const num1 = others.shift();
    const num2 = others.shift();
    if (others.length > 0) {
      return multiply(multiply(num1, num2), ...others);
    }
    const num1Changed = float2Fixed(num1);
    const num2Changed = float2Fixed(num2);
    // 把两个数的小数位数相加
    const baseNum = digitLength(num1) + digitLength(num2);
    const leftValue = num1Changed * num2Changed;
    return leftValue / (window as any).Math.pow(10, baseNum);
  }
  return others[0] || 0;
}

1.4 精确加法

function add(...others) {
  if (others.length > 1) {
    const num1 = others.shift();
    const num2 = others.shift();
    if (others.length > 0) {
      return add(add(num1, num2), ...others);
    }
    const baseNum = (window as any).Math.pow(
      10,
      (window as any).Math.max(
        digitLength(num1),
        digitLength(num2),
      ),
    );
    return (
      (multiply(num1, baseNum) + multiply(num2, baseNum)) / baseNum
    );
  }
  return others[0] || 0;
}

1.5 精确乘法

function subtract(...others) {
  if (others.length > 1) {
    const num1 = others.shift();
    const num2 = others.shift();
    if (others.length > 0) {
      return subtract(subtract(num1, num2), ...others);
    }
    const baseNum = (window as any).Math.pow(
      10,
      (window as any).Math.max(
        digitLength(num1),
        digitLength(num2),
      ),
    );
    return (
      (multiply(num1, baseNum) - multiply(num2, baseNum)) / baseNum
    );
  }
  return others[0] || 0;
}

1.6 精确除法

function divide(...others) {
  if (others.length > 1) {
    const num1 = others.shift();
    const num2 = others.shift();
    if (others.length > 0) {
      return divide(divide(num1, num2), ...others);
    }
    const num1Change = float2Fixed(num1);
    const num2Change = float2Fixed(num2);
    return multiply(
      num1Change / num2Change,
      (window as any).Math.pow(
        10,
        digitLength(num2) - digitLength(num1),
      ),
    );
  }
  return others[0] || 0;
}

1.7 四舍五入

// 四舍五入,且保留小数
function round(num, ratio = 0) {
  const base = (window as any).Math.pow(10, ratio);
  return divide(
    (window as any).Math.round(multiply(num, base)),
    bas
  );
}

1.8 将数据转换为大写

function transferIntoBigNum(num: number): string {
  const strNum: string = (num + '').replace(/^[\s0]+|\s+$/gi, '');
  const mapBigNum: string[] = ['〇','一','二','三','四','五','六','七','八','九','十',];
  const mapDw: string[] = ['个','十','百','千','万','十万','百万','千万','亿',];
  if (num <= 10) {
    return mapBigNum[num || 0];
  }
  const result: string[] = [];
  for (let i = 0, l = strNum.length, j = l - 1; i < l; i++, j--) {
    if (+strNum[i] === 0) {
      if (result[result.length - 1] !== '〇') {
        result.push(mapBigNum[0]);
      }
    } else {
      result.push(mapBigNum[strNum[i]]);
    }
    if (j > 0 && result[result.length - 1] !== '〇') {
      result.push(mapDw[j]);
    }
  }
  let index: number = result.length;
  while (index--) {
    if (result[index] === '〇') {
      result.pop();
    } else if (result[index] === '十') {
      if (num > 100 && num < 1000) {
        result.pop();
      } else {
        break;
      }
    } else {
      break;
    }
  }
  if (result[0] === '一' && result[1] === '十') {
    result.shift();
  }
  return result.join('');
}