美文网首页
JavaScript中数字运算精度丢失问题

JavaScript中数字运算精度丢失问题

作者: 谁把月亮涂黑啦 | 来源:发表于2018-09-27 10:38 被阅读0次

取整

js里取整有好几个方法,比如

+1.20
1.20|0
~~1.20
ParseInt(1.20, 10)
Math.floor(1.20)
Math.trunc(1.20)

如果整数位数字很大,这时候利用位操作(慎用)会出现数值溢出,可以用其他方法代替。
有时候也会遇到字符串转数字的问题,如果是小数,可以先乘以10的倍数得到整数再除以10的倍数得到理想的小数,这样可以避免精度丢失的问题。

项目中有时候会碰到金额的货币转换问题,如果用Number类型进行运算,例如:1235.485/10000 = 0.12354849999999999;可以看到结果为无限循环小数,这时候可以利用数字转字符串来解决,为此我写了乘法和除法的运算方法。
注意:整数位数字如果大于Number.MAX_SAFE_INTEGER === 9007199254740991下列方法将不再适用。

乘法

// 乘法——p 为小数点向右移动的位数
function multiBigInt(n, p = 0) {
  let str = n, i = p;
  if(typeof n === 'number') {
    // .123 === 0.123
    str = `${n}`
  }
  if(p < 0) {
    i = Math.abs(p)
  }
  const pIndex = str.indexOf('.');
  if (pIndex > 1) {
    if(str.slice(pIndex + 1).length <= i) {
      return `${str.slice(0, pIndex)}${str.slice(pIndex + 1).padEnd(i, '0')}`
//    return `${str.slice(0, pIndex)}${str.slice(pIndex) * 10 ** i}`
    }
    return `${str.slice(0, pIndex)}${str.slice(pIndex + 1, pIndex + 1 + i)}.${str.slice(pIndex + 1 + i)}`
  }
  if(pIndex === 0 || pIndex === 1) {
    if(str.slice(pIndex + 1).length <= i) {
      return `${str * 10 ** i}`
    }
    return `${str.slice(pIndex + 1, pIndex + 1 + i)}.${str.slice(pIndex + 1 + i)}`
  }
  return `${str.padEnd(str.length + i, '0')}`
}

Result:

console.log(123, multiBigInt(123, 4))    // "1230000"
console.log(12345.33, multiBigInt(12345.33, 4))    // "123453300"
console.log(12345.123401, multiBigInt(12345.123401, 4))     //"123451234.01"
console.log(0.25, multiBigInt(0.25, 4))    // "2500"

除法

除法——p 为小数点向左移动的位数
function dividedBigInt(n, p=0) {
  let str = n, i = p;
  if (typeof n === 'number') {
    str = `${n}`
  }
  if (p < 0) {
    i = Math.abs(p)
  }
  const pIndex = str.indexOf('.');
  if (pIndex === -1) {
    const strEnd = str.slice(-i).replace(/[0]+$/, '');
    // 当字符串末尾 i 位数字全为 0 时
    if (strEnd === '') {
      return `${str.slice(0, str.length - i)}`;
    }
    // 字符串长度大于小数点左移的位数
    if (str.length > i) {
      return `${str.slice(0, str.length - i)}.${str.slice(str.length - i)}`.replace(/[0]+$/, '')
    }
    return `0.${str.padStart(i, '0')}`.replace(/[0]+$/, '')
  }else if (pIndex > i) {
    const pBefore = str.slice(0, pIndex);
    return `${pBefore.slice(0, pBefore.length - i)}.${pBefore.slice(pBefore.length - i)}${str.slice(pIndex + 1)}`
  }else if (pIndex > 0) {
    return `0.${str.slice(0, pIndex).padStart(i, '0')}${str.slice(pIndex + 1)}`
  }
  return str;
}

Result:

console.log(1236688, dividedBigInt(1236688, 4))    // "123.6688"
console.log(1236600, dividedBigInt(1236600, 4))    // "123.66"
console.log(120, dividedBigInt(120, 4))    // "0.012"
console.log(12366.88, dividedBigInt(12366.88, 4))    // "1.236688"
console.log(123.66, dividedBigInt(123.66, 4))    // "0.012366"

相关文章

网友评论

      本文标题:JavaScript中数字运算精度丢失问题

      本文链接:https://www.haomeiwen.com/subject/egdbiftx.html