记一次产线的JS精度丢失

本文记录了一次生产线上遇到的JS浮点数精度丢失问题,深入探讨了浮点数计算的原理,包括JS中浮点数表示的误差、IEEE-745标准、浮点数规格化处理以及非规范浮点数。解释了为何0.1+0.2不等于0.3,并提出了解决方案:避免在JS中直接进行浮点数计算,或转换为整数计算后再转回浮点数。还分析了Ajax请求与正常HTTP请求的区别,指出Ajax请求中可能出现的精度问题源于JSON解析时数值类型处理。
摘要由CSDN通过智能技术生成

最近生产上出现了一次JS精度丢失的现象,这个问题解决起来不是很难, 但是对于为什么会出现这种情况进行了思考,得到了一些体会,Mark 一下。

这里写图片描述

首先:这个请求是Ajax请求,如果正常的post或者get 请求是不会出现这种问题,原因后续会讲。

首先:先来说下JS精度丢失是什么,总体来说,就是JS表示浮点数的时候会出现误差。包含两类问题:

1、使用JS进行浮点数计算,得到错误的结果。

2、Ajax请求后端返回的数值类型的值大于JS的表示范围(本次产线的场景。)

浮点数计算。

经典的 0.1+0.2!=0.3

产生这个问题的原因是及计算机是二进制的方式保存浮点数,同时又有位数的限制,导致了浮点数精度的缺失。

几乎所有的编程语言都采用IEEE-745标准表示浮点数,这是一种对于实数的近似值数值表现,并不能精确的表示类似0.1这样 的简单的数字。为什么呢?

浮点数:简单来讲浮点数就是小数点逻辑上不固定,跟它对应的就是定点数,小数点位置固定。比如oracle中的Number(5,2),意思就是总长度5位,其中整数3位,小数两位。小数点固定。这种表达方式的缺点就是表达范围和精度比较局限。不利于同时表达特大或者特小的数字。而浮点数却能很好的规避这个缺点,浮点数使用一个有效数字,一个基数,一个指数,以及一个表示正负的符号来表达实数,通过指数达到浮动小数点的效果,例如1.234x10^1和 1.234x10^2 。

IEEE-745:计算机的存储方式是二进制,因此使用计算机表示浮点数的时候基数就变成了2,可以理解为2进制的科学计数法,(尾数用原码;阶码用“移码”;基为2)。

IEEE-745标准定义的浮点数据格式为:(其实有32bit 的单精度和64 bit的双精度,本例只说双精度)

值(尾数)Fraction 指数(阶码)Exponent 符号 Sign
52bits(0-51) 11bits(52-62) 1bit(63)
有效数字 表示小数点在数据中的位置 1–负数;0–正数

按照上面的指数表示方法,一个二进制的浮点数会有不同的表示:

0.00101(2) = 1.01×2−3 = 10.1×2−4

为了提高数据的表示精度同时保证数据表示的唯一性,需要对浮点数做规格化处理。在计算机内,对非0值的浮点数,要求尾数域的最高有效位应为1,称满足这种表示要求的浮点数为规格化表示:把不满足这一表示要求的尾数,变成满足这一要求的尾数的操作过程,叫作浮点数的规格化处理,可以通过尾数移位和修改阶码实现。

即:浮点数的格式变为:

x=
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值