toFixed四舍五入为啥不准确

# toFixed 的问题

1.36.toFixed(1) // 1.4 没有问题
1.31.toFixed(1) // 1.3 没有问题

1.35.toFixed(1) // 1.4 这里的5入
1.45.toFixed(1) // 1.4 这里的5又舍去了。

1.15.toFixed(1) // 1.1 并没有进1 成1.2来凑偶数
1.05.toFixed(1) // 1.1 进1之后反倒成奇数了

1
2
3
4
5
6
7
8
9

# 原因

不是所谓的银行家算法,也不是四舍六入五成双,就是四舍五入

1.15.toPrecision(100)
// 1.149999999999999911182158029987476766109466552734375000000000000000000000000000000000000000000000000
1
2

1.15 在系统中就不是严格上的 1.15,通过这个高精度表示的数字来看,就知道为什么 1.15.toFixed(1) 的结果为什么是1.1了,因为小数点后第二位根本不是5而且4,所以直接舍去了

不管浏览器具体采用的是什么逻辑,通过 js 标准以及这些例子,可以确定 toFixed 方法使用的逻辑是四舍五入,至于为什么部分数字不符合预期,是由于精度问题导致了。就好像为什么 0.1 + 0.2 !== 0.3 是一样的

运算前会转成二进制 误差的来源是在IEE 754 双精度浮点数标准下,二进制数据无法精确的标识小数(一些小数转换成二进制长度会无限循环)

# 解决方法

两个三方库:yatter, decimal-format

import {toFixed} from 'yatter';

console.log(toFixed(87.55, 1)) // 87.6
1
2
3
import DecimalFormat from 'decimal-format';

const df = new DecimalFormat('0.0');
df.format(87.55); // 87.6

df.setRoundingMode(RoundingMode.HALF_EVEN); // 设置为 四舍六入五成双 模式
df.format(87.85) // 87.8
1
2
3
4
5
6
7
最近更新时间: 2025/05/09 09:02:23
最近更新
01
2025/05/05 00:00:00
02
2025/05/01 00:00:00
03
2025/03/15 00:00:00