const a = 7.55;
console.log(a.toFixed(1)) // 7.5
比如上面这代码,如果作为四舍五入计算的话,就会出现遇到5不进位的问题
具体原因可以参考这篇文章 js - tofixed精度丢失问题
附上上面文章的解决方案的ts版(重写Number.prototype.toFixed
)
/**
* 重写toFixed方法,默认toFixed方法遇5不进位
*/
Number.prototype.toFixed = function (n: number) {
if (n > 20 || n < 0) {
throw new RangeError('toFixed() digits argument must be between 0 and 20')
}
// eslint-disable-next-line @typescript-eslint/no-this-alias
const number = this
if (isNaN(number as number) || number >= Math.pow(10, 21)) {
return number.toString()
}
if (typeof n == 'undefined' || n == 0) {
return Math.round(number as number).toString()
}
let result: string | number = 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
}
另一种方法,使用
封装,推荐使用:
Math.round
/**
* 四舍五入+保留小数
* @param num 值
* @param decimal 保留小数的位数
*/
export const toFixed = (num: number, decimal = 0) => {
if (typeof num === 'undefined') {
return ''
}
if (isNaN(num) || num >= Math.pow(10, 21)) {
return ''
}
// 获取保留几位小数
const d = Math.pow(10, decimal)
return (Math.round((num + Number.EPSILON) * d) / d)?.toString()
}