一、浮点数的存储
1.1 概念
1 | // 加法 ===================== |
JavaScript 中所有数字包括整数和小数都只有一种类型 — Number。它的实现遵循 IEEE 754 标准,使用 64 位固定长度来表示,也就是标准的 double 双精度浮点数(相关的还有float 32位单精度)。
64位比特又可分为三个部分:
- 符号位S【第0位】:第 1 位是正负数
符号位(sign)
,0代表正数,1代表负数 - 指数位E【第1位】:中间的 11 位存储
指数(exponent)
,用来表示次方数 - 尾数位M【第12位】:最后的 52 位是
尾数(mantissa 有效数字)
,超出的部分自动进一舍零
为什么 0.1+0.2=0.30000000000000004?
1 | // 0.1 和 0.2 都转化成二进制后再进行运算 |
1.2 精度丢失
十进制是给人看的,但在进行运算之前,必须先转换为计算机能处理的二进制。最后,当运算完毕后,再将结果转换回十进制,继续给人看。精度就丢失于这两次转换的过程中。
二、浮点数运算
2.1 toFixed() 方法
使用定点表示法来格式化一个数值(返回的值是字符串)
1 | var numObj = 12345.6789; |
1 | parseFloat((数学表达式).toFixed(digits)); // toFixed() 精度参数须在 0 与20 之间 |
chrome下有问题情况:
1 | 1.35.toFixed(1) // 1.4 正确 |
2.2 toPrecision() 方法
以指定的精度返回该数值对象的字符串表示。
toPrecision
和toFixed
在数据处理时很容易混淆,共同点是把数字转成字符串
供展示使用。注意在计算的中间过程不要使用,只用于最终结果
。
区别:
toPrecision()
:是处理精度,精度是从左至右第一个不为0的数开始数起。toFixed()
:是小数点后指定位数取整,从小数点开始数起。1
2
3
4
5var numObj = 5.123456;
numObj.toPrecision(1) //输出 5
numObj.toPrecision(2) //输出 5.1
numObj.toPrecision(5) //输出 5.1235
numObj.toPrecision() //输出 5.123456
三、工具函数:解决精度丢失
3.1 数据展示类
1 | function strip(num, precision = 12) { |
3.2 数据运算类
小数转成整数来运算,之后再转回小数
1 | /** |
以上方法能适用于大部分场景。遇到科学计数法如 2.3e+1(当数字精度大于21时,数字会强制转为科学计数法形式显示)时还需要特别处理一下。
1 | 'use strict' |
四、类库
4.1 Math.js
Math.js 是专门为 JavaScript 和 Node.js 提供的一个广泛的数学库。它具有灵活的表达式解析器,支持符号计算,配有大量内置函数和常量,并提供集成解决方案来处理不同的数据类型
像数字,大数字(超出安全数的数字),复数,分数,单位和矩阵。 功能强大,易于使用。
官网
GitHub
4.2 decimal.js
为 JavaScript 提供十进制类型的任意精度数值。
官网
GitHub