toFixed语法:
var num = 5.56789;
var n=num.toFixed(2);
toFixed可以将一个数字转为一个字符串,并且保留指定的小数位数; 同时,toFixed会进行四舍五入
问题就出在这里,toFixed进行四舍五入时的表现不尽如人意,
在Chrome浏览器中,实际测试结果:
所以,当你只是用toFixed来进行补零,也就是说num.toFixed(n)中,n >= num时toFixed才是安全的;当n < num时,它会自动进行四舍五入,但是它四舍五入的结果又不对,我们项目中之前toFixed参与了大量的计算,导致精度丢失,所以我现在正在修复这些问题
当你需要用toFixed,并且希望它的四舍五入是正确的,这里提供2种解决思路:
1、使用decimal.js
import Decimal from 'decimal.js'
var num = 1.335
console.log('toFixed', num.toFixed(2)) // 1.33
console.log('Decimal', Decimal(num).toFixed(2)) // 1.34
或者是其他库:number-precision/bignumber.js,看你们项目中用的是哪个
2、重写toFixed方法
// 重写toFixed方法
Number.prototype.toFixed = function (n) {
if (n > 20 || n < 0) {
throw new RangeError(
'toFixed() digits argument must be between 0 and 20'
)
}
const number = this
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('.')
// 整数的情况
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
}
result = integer + '.' + decimal.substr(0, n)
const last = decimal.substr(n, 1)
// 四舍五入,转换为整数再处理,避免浮点数精度的损失
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
}
如果你觉得这篇文章对你有用,可以看看作者封装的库xtt-utils,里面封装了非常实用的js方法。如果你也是vue开发者,那更好了,除了常用的api,还有大量的基于element-ui组件库二次封装的使用方法和自定义指令等,帮你提升开发效率。不定期更新,欢迎交流~