LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

[点晴永久免费OA]关于 js 中的精度丢失问题

freeflydom
2023年6月26日 11:31 本文热度 640

前言

在 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 转化为二进制的结果是:1000

小数部分:乘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 转化为二进制的结果是:0.0001100110011...

如何存储?

js 中 Number 类型使用 IEEE 754 标准 64 位存储,为每个数值分配 64 位存储空间,以科学计数法的方式进行存储。形式如下:

1.xxxxxx * 2 ^ n 



64位存储空间分为3个部分,包括 符号位指数位小数位,如下图所示:


符号位占 1 位,标记数值的正负,0 表示正数,1 表示负数。

指数位占 11 位,值为一个固定值 1023 (IEEE 754 标准) + 科学计数法中的指数值,再将其转为 11 位二进制。比如 0.1 = 0.00011001... = 1.1001... * 2 ^ (-4),指数位就为 1023 + (-4) = 1019,用 11 位二进制表示为 01111111011

小数位占 52 位,用来存放小数点后的数值,以 0.1 为例,由于小数位只能存储 52 位,又因为第 53 位为 1,所以截取需要往前进一位再保存,这里就造成了第一次的精度丢失。

相同的道理,所以 0.1 和 0.2 在内存中就是这样的:

如何计算?

最后就是将 64 位双精度浮点数相加,首先我们把偏移量还原对齐,再进行相加,如下图所示:


相加后发现小数部分有 53 位,由于小数位只能存储 52 位,因此需要再次进行截取,这里就造成了第二次的精度丢失。将这个结果转化为十进制就得到了一开始我们打印的结果。

这也就是为什么 0.1 + 0.2 不等于 0.3 的原因。

解决方法

可以使用一些第三方库来解决,例如:

  • bignumber.js:提供了超高精度的数字处理能力,可以解决精度丢失问题。官方文档

  • decimal.js:可以精确表示浮点数,解决精度丢失问题。官方文档

总结

  1. js 用二进制处理数据,用 IEEE 754 双精度浮点数标准存储 Number 类型。

  2. 精度丢失是由于 IEEE 754 标准存储位有限导致的。

  3. 过程中会有两次精度丢失,一次在存储,一次在相加。


原文链接



该文章在 2023/6/26 11:32:06 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved