前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库toFixed 舍入 精度
JavaScript值与类型

toFixed 返回什么类型?为什么 1.005.toFixed(2) 是 1.00 而不是 1.01?

toFixed(n) 返回的是字符串。它确实按四舍五入保留 n 位小数,但舍入的对象是数字在内存里的真实二进制值。1.005 实际存成了 1.00499999…,所以 (1.005).toFixed(2) 得到 '1.00'。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#值与类型
先看核心答案读代码示例
理解线索

`toFixed` 的三个特点

  1. 返回字符串(1).toFixed(2) 是 '1.00',这样才能保留末尾的 0
  2. 按真实值舍入舍入前先看二进制存的精确值,看起来是 5 的那一位可能其实是 4999…
  3. 参数范围位数可以是 0~100,超出范围抛 RangeError

很多人以为 toFixed 用的是「银行家舍入」,其实不是。(2.5).toFixed(0) 是 '3',(1.45).toFixed(1) 是 '1.4',前者是正常四舍五入,后者是因为 1.45 存的是 1.4499…。

核心回答

先记住这个答案

toFixed(n) 把数字格式化成保留 n 位小数的字符串,返回类型是 string,所以才能表示 '1.00' 这种末尾带 0 的结果。它的舍入规则是标准的四舍五入,但舍入的是数字在内存里的真实值,而不是你在代码里写的十进制。1.005 用二进制存不准,实际值是 1.00499999999999989…,第三位小数其实是 4,所以保留两位得到 '1.00'。

  • toFixed 返回字符串,参与运算前要转回数字
  • 舍入按真实二进制值,不是按你写的十进制
  • 1.005 的二进制近似会影响舍入
  • 绝对值不小于 1e21 时直接返回科学计数法字符串

看上去「舍错」的几个例子

把几个数的 toFixed 结果和它们的真实值放在一起看,就知道问题出在哪。

对照真实存储值JavaScript
const cases = [[1.005, 2], [1.045, 2], [1.255, 2], [1.45, 1], [2.5, 0]]
for (const [n, digits] of cases) {
  // toPrecision(20) 能把内存里的真实值多显示几位
  console.log(n, '->', n.toFixed(digits), '真实值', n.toPrecision(20))
}
console.log(typeof (1).toFixed(2), (1).toFixed(2))
查看输出与解释
1.005 -> 1.00 真实值 1.0049999999999998934
1.045 -> 1.04 真实值 1.0449999999999999289
1.255 -> 1.25 真实值 1.2549999999999998934
1.45 -> 1.4 真实值 1.4499999999999999556
2.5 -> 3 真实值 2.5000000000000000000
string 1.00

最后一行先看:返回值的类型是 string。前面几行看真实值那一列就明白了,1.005、1.045、1.255、1.45 存进内存后都比字面值小一点点,舍入位变成了 4,于是全部舍掉。2.5 可以用二进制精确表示,所以正常进位成 3。 也就是说,toFixed 本身的算法没有错,错的是「1.005」这个数在 Number 里根本不存在。你拿到的是离它最近的一个二进制浮点数,而这个数恰好略小于 1.005。

几个容易被忽视的行为

除了舍入,toFixed 还有几处跟直觉不一样的地方,写格式化函数时会碰到。

大数返回科学计数法
数值的绝对值大于等于 1e21 时,toFixed 不再按位数格式化,而是直接返回和 String() 一样的结果,(1e21).toFixed(2) 得到 '1e+21'。另外,即使小于 1e21,只要超过 2^53,整数部分的末几位本来就不精确,保留小数也没有意义。
负数会出现 -0.00
(-0.0001).toFixed(2) 得到 '-0.00'。数值很小的负数舍到 0 以后,负号仍然保留。显示金额时如果不想看到 -0.00,要在格式化前后单独处理。
位数参数超出范围会报错
参数可以是 0~100,传 101 会抛 RangeError。不传参数等于传 0,(3.7).toFixed() 得到 '4'。
回答前,多想一步

容易答错的地方

以为 toFixed 返回数字
(0.1 + 0.2).toFixed(2) + 1 得到的是 '0.301',因为字符串加数字是拼接。需要继续计算时要先 Number() 或 parseFloat() 转回来。
以为用 Math.round(x * 100) / 100 就能解决
乘法同样有精度问题。1.005 * 100 算出来是 100.49999999999999,Math.round 之后还是 100,结果仍然是 1。这个写法只是把误差换了个地方出现。
以为 toFixed 用的是银行家舍入
银行家舍入是「四舍六入五取偶」。(2.5).toFixed(0) 是 '3',(0.5).toFixed(0) 是 '1',都说明遇到正好一半时是向上进位,不是取偶。那些看起来像取偶的例子,都是真实值略小于字面值造成的。
试着用自己的话回答

面试官还会怎么问?

金额计算怎么做才靠谱?

最常见的做法是全程用整数「分」来存和算,只在显示时除以 100 再格式化。比如 19.9 元存成 1990 分,加减乘都是整数运算,不会有误差。注意元转分这一步本身也要处理:19.9 * 100 算出来是 1989.9999999999998,要写成 Math.round(19.9 * 100)。涉及除法、利率这类必然产生小数的计算,用 decimal.js、big.js 这类十进制库,它们用字符串或整数数组按十进制运算。

想要「正确」的四舍五入,有没有简单写法?

可以先把数字转成字符串,在字符串层面处理小数位,或者借助指数表示绕开乘法误差,比如 Number(Math.round(Number(x + 'e2')) + 'e-2')。这里字符串 '1.005e2' 会被解析成精确的 100.5,舍入后得到 101,再除回去得到 1.01。这类写法能处理大多数显示场景,但真正的金额计算还是建议用整数或十进制库。

toFixed 和 toPrecision 有什么区别?

toFixed(n) 固定小数点后的位数,toPrecision(n) 固定总的有效数字位数。(123.456).toFixed(1) 是 '123.5',(123.456).toPrecision(4) 也是 '123.5',但 (123.456).toPrecision(2) 会变成 '1.2e+2'。显示金额用前者,显示科学数据时常用后者。

从一道题,走向一组知识

把知识连起来

值与类型

怎么把十进制数转成二进制、八进制、十六进制字符串?有什么限制?

toFixed 和 toString 都是把数字转成字符串,一个控制小数位数,一个控制进制。

值与类型

为什么 0.1 + 0.2 不等于 0.3?浮点数该怎么比较?

1.005 舍错和 0.1 + 0.2 不等于 0.3 是同一个原因:十进制小数存不准。

参考资料

  • JavaScript:值与类型参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 看上去「舍错」的几个例子
  3. 几个容易被忽视的行为
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑