toFixed方法注意点

遇到的问题:

js的浮点数运算不准确,(a + b).toFixed(2)能解决一部分问题,但并不完美。

1
2
3
4
5
6
7
8
0.1 + 0.2 //0.30000000000000004
(0.1 + 0.2).toFixed(2) // 0.30
0.815 + 0.1 // 0.9149999999999999
(0.815 + 0.1).toFixed(2) // 0.91,错误!期望0.92
// toFixed并不是我们通常理解的“四舍五入”,而是“四舍六入五留双”
// 简单来说就是:四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为奇应舍去,五前为偶要进一。
(0.225).toFixed(2) // 0.23
(0.235).toFixed(2) // 0.23,错误!期望0.24

解决方案

网络上有很多种解决方案,可以修正toFixed方法,也可以重新定义四则运算。重新定义四则运算,最为规范,但使用麻烦,故我最终选择了修正toFixed。 声明:源码来源于网络,本文只是添加了注释和分析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// 直接替换原型链上的方法,方便使用
Number.prototype.toFixed = function (n) {
// n为期望保留的位数,超过限定,报错!
if (n > 20 || n < 0) {
throw new RangeError('toFixed() digits argument must be between 0 and 20');
}
// 获取数字
const number = this;
// 如果是NaN,或者数字过大,直接返回'NaN'或者类似'1e+21'的科学计数法字符串
if (isNaN(number) || number >= Math.pow(10, 21)) {
return number.toString();
}
// 默认保留整数
if (typeof (n) == 'undefined' || n == 0) {
return (Math.round(number)).toString();
}

// 先获取字符串
let result = number.toString();
// 获取小数部分
const arr = result.split('.');

// 整数的情况,直接在后面加上对应个数的0即可
if (arr.length < 2) {
result += '.';
for (let i = 0; i < n; i += 1) {
result += '0';
}
return result;
}

// 整数和小数
const integer = arr[0];
const decimal = arr[1];
// 如果已经符合要求位数,直接返回
if (decimal.length == n) {
return result;
}
// 如果小于指定的位数,补上
if (decimal.length < n) {
for (let i = 0; i < n - decimal.length; i += 1) {
result += '0';
}
return result;
}
// 如果到这里还没结束,说明原有小数位多于指定的n位
// 先直接截取对应的位数
result = integer + '.' + decimal.substr(0, n);
// 获取后面的一位
let last = decimal.substr(n, 1);
if (/^\d(9){5,}[89]$/.test(decimal.substr(n))) {
last += last + 1;
}
// 大于等于5统一进一位
if (parseInt(last, 10) >= 5) {
// 转换倍数,转换为整数后,再进行四舍五入
const x = Math.pow(10, n);
// 进一位后,转化还原为小数
result = (Math.round((parseFloat(result) * x)) + 1) / x;
// 再确认一遍
result = result.toFixed(n);
}

return result;
};
本文结束感谢您的阅读

本文标题:toFixed方法注意点

文章作者:陈宇(cosyer)

发布时间:2018年09月14日 - 20:09

最后更新:2019年07月01日 - 02:07

原始链接:http://mydearest.cn/toFixed%E6%96%B9%E6%B3%95%E6%B3%A8%E6%84%8F%E7%82%B9.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

坚持原创技术分享,您的支持将鼓励我继续创作!