超实用的JS方法(二)--- 处理计算精度

139 阅读1分钟

获取代码地址:gitee.com/wmbuding/li…

众所周知,在JS环境里数字类型0.1+0.2不等于0.3,至于为什么这里呢就不展开探讨,大家自行百度谷歌便有很好的答案~今天为大家带来的是解决这方便的方法----fixCalc。一共有四个参数,前两个分别是要计算的单位,第三个是算术类型1 相乘 2相除 3相加 4相减。最后一个参数是所要的长度,多截取,少补零(若有第四个参数返回的是一个字符串类型)

  // 例子
  fixCalc(0.1, 0.2, 3) // => 0.1+0.2=0.3
  // 传第四个参数
  fixCalc(0.1, 0.2, 3, 2) // => 0.30

源码如下:

type Num = string | number
interface FixCalcFn {
  (num1: number, num2: number, type?: number, s?: any): number | string
}

/**
 * 截取数值长度或者补零
 * @param {Number} x 传入值,需要补零或者截取长度得值
 * @param {Object} ss 所需长度,多截少补零
 */
export const toDecimal = (val: Num, ss: number) => {
  if (isNaN(parseFloat(`${val}`))) return 0
  let s = val.toString()
  let rs = s.indexOf('.')
  if (rs !== -1 && s.length > rs + ss) {
    return s.substr(0, rs + ss + 1)
  }
  // 数值长度小于传值长度(ss)
  if (rs === -1) {
    rs = s.length
    s += '.'
  }

  while (s.length <= rs + ss) {
    s += '0'
  }
  return s
}

// 获取数字以及长度,用于计算
const getNums = (num: Num) => {
  const str = `${num}`
  let len = 0
  try {
    len += str.split('.')[1].length
  } catch (e) { }
  return {
    len,
    num: Number(str.replace('.', '')),
  }
}

/**
 * num1 要计算得第一个数字
 * num2 要计算得第二个数字
 * type 计算方式 1 相乘 2相除 3相加 4相减
 * s  所需长度,多截少补零
 */
const fixCalc: FixCalcFn = (num1, num2, type = 1, s) => {
  const nums1 = getNums(num1)
  const nums2 = getNums(num2)
  const t1 = nums1.len
  const t2 = nums2.len
  const n1 = nums1.num
  const n2 = nums2.num
  let r: Num = 0
  if (type === 1) {
    r = (n1 * n2) / Math.pow(10, t1 + t2)
  }
  if (type === 2) {
    r = (n1 / n2) * Math.pow(10, t2 - t1)
  }
  if (type === 3) {
    const m = Math.pow(10, Math.max(t1, t2))
    r = (num1 * m + num2 * m) / m
  }
  if (type === 4) {
    const m = Math.pow(10, Math.max(t1, t2))
    const n = t1 >= t2 ? t1 : t2
    r = (num1 * m - num2 * m) / m
    r = r.toFixed(n)
  }
  if (s !== null && s !== undefined) {
    r = toDecimal(r, s)
  }
  return r
}
export default fixCalc