遇到的问题
日环比计算方式:今日数据(小数形式)- 昨日数据(小数形式)。
有时会出现下面问题:
const val = 1.91 - 1.11; // 0.7999999999999998
问题原因
要搞清楚float累加为什么会产生误差,必须先大致理解float在机器里怎么存储的,这里只介绍一下组成
由上图可知, 浮点数由: 符号位 + 指数位 + 尾数部分, 三部分组成。由于机器中都是由二进制存储的,那么一个10进制的小数如何表示成二进制。
例如: 8.25转成二进制为1000.01, 这是因为 1000.01 = 1*2^3 + 0*2^2 + 0*2^1 + 0*2^0 + 0*2^-1 + 2*2^-2 = 1000.01
.
(2)float的有效位数是6-7位,这是为什么呢?因为位数部分只有23位,所以最小的精度为1*2^-23
在 10^-6
和 10^-7
之间,接近 10^-7
。
那么为什么float累加会产生误差呢,主要原因在于两个浮点数累加的过程。
减法运算,转化成加法运算处理,同样存在上述问题。
解决方案
使用下面定制化 toFloat
函数,对出现小数运算的地方进行显示设置。
// 四舍五入修正代码
Number.prototype.toFloat = function(n) {
n = n ? parseInt(n) : 0;
if (n <= 0) {
return Math.round(this);
}
let num = Math.round(this * Math.pow(10, n)) / Math.pow(10, n); //四舍五入
num = Number(num).toFixed(n); //补足位数
return Number(num);
};
故问题中描述的部分解决办法是:
const val = (1.91 - 1.11).toFloat(2); // 0.8
【参考资料】