[点晴永久免费OA]关于 js 中的精度丢失问题
当前位置:点晴教程→点晴OA办公管理信息系统
→『 经验分享&问题答疑 』
前言在 Javascript 中,由于采用了 IEEE 754 标准的浮点数表示方法,可能会导致精度丢失问题。这主要是因为浮点数在内存中以二进制的形式存储,而某些十进制数无法精确地转换成二进制表示。当进行计算时,就会出现舍入误差。 例如以下示例:
结果不精确是因为 0.1 和 0.2 无法用二进制无法精确地表示出来,进行运算时也会存在误差。 本文将以此为例,从二进制转化,存储到计算来分析造成这一结果的根本原因,文章篇幅不多,希望看完后可以给你带来一些收获...... 如何转化?首先我们要清楚整数和小数是如何转化为二进制的。 整数部分:除2取余 + 逆序排列,示例如下: 8 / 2 = 4 ...... 0 4 / 2 = 2 ...... 0 2 / 2 = 1 ...... 0 1 / 2 = 0 ...... 1 整数 8 转化为二进制的结果是: 小数部分:乘2取整 + 顺序排列,示例如下: 0.1 * 2 = 0.2 ...... 0 0.2 * 2 = 0.4 ...... 0 0.4 * 2 = 0.8 ...... 0 0.8 * 2 = 1.6 ...... 1 0.6 * 2 = 1.2 ...... 1 0.2 * 2 = 0.4 ...... 0 ... 小数 0.1 转化为二进制的结果是: 如何存储?js 中 Number 类型使用 IEEE 754 标准 64 位存储,为每个数值分配 64 位存储空间,以科学计数法的方式进行存储。形式如下: 1.xxxxxx * 2 ^ n 64位存储空间分为3个部分,包括 符号位、指数位 和 小数位,如下图所示:
符号位占 1 位,标记数值的正负, 指数位占 11 位,值为一个固定值 1023 (IEEE 754 标准) + 科学计数法中的指数值,再将其转为 11 位二进制。比如 0.1 = 0.00011001... = 1.1001... * 2 ^ (-4),指数位就为 1023 + (-4) = 1019,用 11 位二进制表示为 小数位占 52 位,用来存放小数点后的数值,以 0.1 为例,由于小数位只能存储 52 位,又因为第 53 位为 1,所以截取需要往前进一位再保存,这里就造成了第一次的精度丢失。 相同的道理,所以 0.1 和 0.2 在内存中就是这样的:
如何计算?最后就是将 64 位双精度浮点数相加,首先我们把偏移量还原对齐,再进行相加,如下图所示:
相加后发现小数部分有 53 位,由于小数位只能存储 52 位,因此需要再次进行截取,这里就造成了第二次的精度丢失。将这个结果转化为十进制就得到了一开始我们打印的结果。 这也就是为什么 0.1 + 0.2 不等于 0.3 的原因。 解决方法可以使用一些第三方库来解决,例如: 总结
该文章在 2023/6/26 11:32:06 编辑过 |
关键字查询
相关文章
正在查询... |