【JS】toFixed()无法精准保留小数的解决方案

情景复现:

发现用 toFiexd()  四舍五入保留小数有时不是很精确,接下来用 a = 8.0345,b=8.045,举例如下:

var a = 8.035;
console.log(a.toFixed(2)) // 8.04
var b = 8.045;
console.log(b.toFixed(2)) // 8.04

不难看出 a 四舍五入保留两位小数为 8.04,正确;而 b 四舍五入保留两位小数应该为 8.05;

计算精度丢失的原因:

js采用64位浮点数表示法(几乎所有现代编程语言所采用),这是一种二进制表示法。二进制浮点数表示法并不能精确表示类似 0.1 这样简单的数字。

目前这个问题不只在js中才会出现,在任何使用二进制浮点数的编程语言中都会出现。

解决方案:

保留两位小数:
var a = 8.035;
var b = 8.045;
function number(data){
    var value = Math.round(parseFloat(data) * 100) / 100;
    var d = value.toString().split(".");
    if (d.length == 1) {
        value = value.toString() + ".00";
        return value;
    }
    if (d.length > 1) {
        if (d[1].length < 2) {
            console.log(d[1])
            value = value.toString() + "0";
        }
        return value;
    }
}
console.log(number(a));  // 8.04
console.log(number(b));  // 8.05
自定义封装:

方案一: 使用 big.js(如果有大量连续的计算推荐使用)

  • 既解决了浮点数计算精度丢失问题,又解决了 toFixed() 四舍五入精度丢失问题。
  • big.js 是 big.jsbignumber.jsdecimal.js 三姐妹中功能最少的,但也是体积最小的,压缩版只有3k,对于处理js精度丢失已经足够用了。
  import Big from 'big.js'
 
  // 运算
  const plus = Big(0.1).plus(0.2); // 加
  const minus = Big(0.3).minus(0.1); // 减
  const mul = Big(10.22).times(100); // 乘
  const div = Big(2.4).div(0.8); // 除
 
  // toFixed
  const fixed = new Big(6.265).toFixed(2); // 6.27
 
  console.log(
    plus.toNumber(),
    minus.toNumber(),
    mul.toNumber(),
    div.toNumber()
  )
  // 0.3 0.2 1022 3

 方案二:有具体要求精确到第几位,用科学计数法对运算结果进行四舍五入

function round(number, precision) {
    return Math.round(+number + 'e' + precision) / Math.pow(10, precision);
}
 
round(8.1234567, 5);    // 8.12346

或者: 

function number(data,n){
    var numbers = '';
    // 保留几位小数后面添加几个0
    for (var i = 0; i < n; i++) {
        numbers += '0';
    }
    var s = 1 + numbers;
    // 如果是整数需要添加后面的0
    var spot = "." + numbers;
    // Math.round四舍五入  
    //  parseFloat() 函数可解析一个字符串,并返回一个浮点数。
    var value = Math.round(parseFloat(data) * s) / s;
    // 从小数点后面进行分割
    var d = value.toString().split(".");
    if (d.length == 1) {
        value = value.toString() + spot;
        return value;
    }
    if (d.length > 1) {
        if (d[1].length < 2) {
            value = value.toString() + "0";
        }
        return value;
    }
}

// 例如:8.1235678 保留五位小数
number(8.12356,5); 

猜你喜欢

转载自blog.csdn.net/leoxingc/article/details/134840376