Henry Henry
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)

Henry

小学生中的前端大佬
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)
  • JavaScript

    • js 编码指南
    • 日期使用斜杠 点 中划线分隔的不同
    • forEach 会改变原数组值吗
    • 前端表单验证常用的正则表达式 - reg
    • JS 如何取得 URL 里的参数
    • JavaScript 数组去重
    • JavaScript 循环中断研究与总结-关键字篇
    • JavaScript 循环中断研究与总结-用法篇
    • js 中的 Error
    • 跳出 forEach
    • Location 对象
    • Date 方法预览
    • Reg 正则中的问题
    • JavaScript toFixed() 方法
      • 定义和用法
      • 语法
      • 参数 描述
      • 返回值
      • 问题
        • 整数如何直接调用
        • 精度问题
    • query 和 params 的使用区别
    • axios post 请求中下载文件流
    • 实用的 js 技巧
    • JS 之数组的几个不 low 操作
    • 深入浅出深拷贝与浅拷贝
    • 如何实现一个深拷贝
    • 使用 iframe 中的一些问题
    • 在 js 中更好地使用数组
    • echarts 在坐标轴两侧各增加一格坐标
    • 从头认识js的事件循环模型
    • moment 根据周截至日算出指定月有几周及开始结束日期
    • 正则 reg 中 /number 的用法
    • 正则 reg 中 match 和 exec 异同
  • TypeScript

  • Vue

  • ElementUI

  • React

  • AntD

  • 前端
  • JavaScript
Henry
2017-07-20
目录

JavaScript toFixed() 方法

简单介绍一下 JavaScript toFixed() 方法和使用中的问题

# 定义和用法

toFixed() 方法可把 Number 四舍五入为指定小数位数的数字, 如果是整数的话会在小数点后面补齐 0

# 语法

NumberObject.toFixed(num)

# 参数 描述

参数 描述
num 必需 规定小数的位数, 是 0 ~ 20 之间的值, 包括 0 和 20 , 有些实现可以支持更大的数值范围. 如果省略了该参数, 将用 0 代替.

# 返回值

返回 NumberObject 的字符串表示, 不采用指数计数法, 小数点后有固定的 num 位数字. 如果必要, 该数字会被舍入, 也可以用 0 补足, 以便它达到指定的长度. 如果 num 大于 le+21 , 则该方法只调用 NumberObject.toString() , 返回采用指数计数法表示的字符串.

# 问题

# 整数如何直接调用

var num = 12
alert(num.toFixed(4))
// 可以正常弹出
1
2
3
alert(12. toFixed(4))
// 不可以弹出
// 报错:Uncaught SyntaxError: Invalid or unexpected token
// 原因:认为 12 后面的点是小数点
1
2
3
4
//修改
alert((12).toFixed(4))
// 可以正常弹出
// 原因:将 12 括起来, 让其认为是一个完整的数值
1
2
3
4

# 精度问题

例子:

1.35.toFixed(1) // 1.4 正确
1.335.toFixed(2) // 1.33  错误
1.3335.toFixed(3) // 1.333 错误
1.33335.toFixed(4) // 1.3334 正确
1.333335.toFixed(5) // 1.33333 错误
1.3333335.toFixed(6) // 1.333333 错误
1
2
3
4
5
6

关于这个的原因可以看看网上大佬的分析: 为什么(2.55).toFixed(1)等于 2.5? - 知乎 (opens new window)

解决方法也有很多, 主要就是判断保留指定位数的最后一位小数是否是 5

第一种修复方式: 判断最后一位小数为 5 的, 改成 6, 再调用 toFixed. 例如 1.335(调用 toFixed(2) 结果为 1.33)先修改为 1.336, 在调用 toFixed(2) , 得到的结果是 1.34, 符合预期.

第二种修复方式: 将数字先进行放大指定倍数, 使最后一位小数显示成个位数, 然后加上一个 0.5 后, 使最后一位进位(如果最后一位大于等于 5), 再调用 parsInt() 去尾并缩小相同倍数. 例如 1.335 放大 100 倍后是 133.5, 加上 0.5 后是 134.0, 调用 parseInt() 得到 134, 再缩小 100 倍得到 1.34, 结果符合预期.

第三种修复方式: 在调用 toFixed() 方法前, 先给数字补一个极小值, 然后再调用 toFixed() 方法. 例如 1.335 加上一个极小值(0.00000001)后是 1.33500001, 然后调用 toFixed(2)得到 1.34, 结果符合预期. 这个极小值只要不影响最后结果, 可以根据要保留的小数位数决定取多少, 但也不能太小了(例如 1.3350000001.toFixed(2) 结果是 1.34, 而 1.33500000000000001.toFixed(2) 结果是 1.33).

这里就推荐下面这种吧

/**
 * @description: 解决 toFixed 精度问题
 * @param {Number} number 待格式化的数字
 * @param {Number} digits 小数位数
 * @param {Boolean} flag 整数时是否用 0 补齐小数位数, 默认 true
 * @return {Number} 格式化后的数字
 */
function toFixed (number, digits, flag = true) {
  number = +number
  digits = +digits
  if (digits > 20 || digits < 0) {
    throw new RangeError('toFixed() digits argument must be between 0 and 20')
  }
  if (isNaN(number) || number >= Math.pow(10, 21)) {
    return number.toString()
  }
  if (typeof digits === 'undefined' || digits === 0) {
    return Math.round(number).toString()
  }

  let result = number.toString()
  const arr = result.split('.')

  // 整数的情况
  if (arr.length < 2) {
    return `${result}${flag ? `.${new Array(digits).fill(0).join('')}` : ''}`
  }

  const [integer, decimal] = arr
  if (decimal.length === digits) {
    return result
  }

  if (decimal.length < digits) {
    return `${result}${flag ? `.${new Array(digits - decimal.length).fill(0).join('')}` : ''}`
  }

  result = integer + '.' + decimal.substr(0, digits)
  const last = decimal.substr(digits, 1)
  // 四舍五入,转换为整数再处理,避免浮点数精度的损失
  if (parseInt(last, 10) >= 5) {
    const x = Math.pow(10, digits)
    result = (Math.round(parseFloat(result) * x) + (integer >= 0 ? 1 : -1)) / x
    result = result.toFixed(digits)
  }

  return result
}
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

参考资料:

  • js 中 toFixed 精度问题的解决办法 - 简书 (opens new window)
  • JavaScript 中 Number.prototype.toFixed 方法五舍六入的问题 - whinc 的个人空间 - OSCHINA (opens new window)
编辑 (opens new window)
#Js
上次更新: 5/27/2023, 1:02:05 PM
Reg 正则中的问题
query 和 params 的使用区别

← Reg 正则中的问题 query 和 params 的使用区别→

最近更新
01
version 1.15
07-01
02
version 1.14
06-27
03
version 1.13
06-27
更多文章>
Theme by Vdoing | Copyright © 2017-2023 HenryTSZ | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式