前端计算数字精度丢失问题解决方法记录 | 京东云技术团队

京东云开发者
• 阅读 75

在日常一些需求中,总会遇到一些需要前端进行手动计算的场景,那么这里需要优先考虑的则是数字精度问题!具体请看下面截图

前端计算数字精度丢失问题解决方法记录 | 京东云技术团队

如图所示,在JavaScript进行浮点型数据计算当中,会出现计算结果“不正确”的现象。

我们知道浮点型数据类型主要有:单精度float、双精度double。

浮点型简单来说就是表示带有小数的数据,而恰恰小数点可以在相应的二进制的不同位置浮动,可能是因为这样就被定义成浮点型了。(不得不佩服这文化程度,定义个数据名称都这么有深度~)

但是!!!

JavaScript 存储小数和其它语言如 Java 和 Python 都不同,JavaScript 中所有数字包括整数和小数都只有一种类型 即 Number类型 它的实现遵循 IEEE 754 标准,IEEE 754 标准的内容都有什么,这个咱不用管,我们只需要记住以下一点:

javascript以64位双精度浮点数存储所有Number类型值,即计算机最多存储64位二进制数。

对于double型数据(双精度浮点数),其长度是8个字节(大小),右边52位用来表示小数点后面的数字,中间11位表示e(exponent)小数点移动的位数,左边一位用来表示正负。如图所示:

前端计算数字精度丢失问题解决方法记录 | 京东云技术团队

只要知道了这一点,那我们就可以对症下药(解决问题):

解决方案 ①

Number(parseFloat(20.24*100).toPrecision(16))

存储二进制时小数点的偏移量最大为52位,最多可表示的十进制为9007199254740992,对应科学计数尾数是 9.007199254740992,这也是 JavaScript 最多能表示的精度。它的长度是 16,所以可以使用 toPrecision(16) 来做精度运算。

通过先转为浮点型计算,然后做精度运算后再转为Number类型即可。

解决方案 ②

通过引入number-precision进行计算,步骤如下:

  • Install
npm install number-precision --save

  • Methods
NP.strip(num)         // strip a number to nearest right number
NP.plus(num1, num2, num3, ...)   // addition, num + num2 + num3, two numbers is required at least.
NP.minus(num1, num2, num3, ...)  // subtraction, num1 - num2 - num3
NP.times(num1, num2, num3, ...)  // multiplication, num1 * num2 * num3
NP.divide(num1, num2, num3, ...) // division, num1 / num2 / num3
NP.round(num, ratio)  // round a number based on ratio

  • Usage
import NP from 'number-precision'
NP.strip(0.09999999999999998); // = 0.1
NP.plus(0.1, 0.2);             // = 0.3, not 0.30000000000000004
NP.minus(1.0, 0.9);            // = 0.1, not 0.09999999999999998
NP.times(3, 0.3);              // = 0.9, not 0.8999999999999999
NP.divide(1.21, 1.1);          // = 1.1, not 1.0999999999999999
NP.round(0.105, 2);            // = 0.11, not 0.1

更多解决方案敬请关注后续更新,希望对您有帮助~

作者:京东零售 黄宏峰

来源:京东云开发者社区 转载请注明来源

点赞
收藏
评论区
推荐文章
Easter79 Easter79
2年前
typeScript数据类型
//布尔类型letisDone:booleanfalse;//数字类型所有数字都是浮点数numberletdecLiteral:number6;lethexLiteral:number0xf00d;letbinaryLiteral:number0b101
Wesley13 Wesley13
2年前
java浮点型精度丢失浅析
java浮点型数值在运算中会出现精度损失的情况,在业务要求比较高比如交易等场景,一般使用BigDecimal来解决精度丢失的情况。最近一个同事在使用BigDecimal时仍然出现了精度损失,简略记录一下测试用例代码如下@Testpublicvoidfd(){doubleabc
Wesley13 Wesley13
2年前
java四类八种基本类型
整型byte字节型short短整型int            普通整型long长整型浮点型float        单精度double    双精度逻辑型boolean 只有true或者false两个值字符型char字符型
Wesley13 Wesley13
2年前
Java:利用BigDecimal类巧妙处理Double类型精度丢失
本篇要点简单描述浮点数十进制转二进制精度丢失的原因。介绍几种创建BigDecimal方式的区别。整理了高精度计算的工具类。学习了阿里巴巴Java开发手册关于BigDecimal比较相等的规定。经典问题:浮点数精度丢失精度丢失的问题是在其他计算机语言中也都会出
Wesley13 Wesley13
2年前
Java中的BigDecimal类和int和Integer总结
前言我们都知道浮点型变量在进行计算的时候会出现丢失精度的问题。如下一段代码:System.out.println(0.050.01);System.out.println(1.00.42);System.out.println(4.015100);System.out.println(1
Wesley13 Wesley13
2年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
2年前
MySQL的一些小问题
在建表的时候,总有一些模糊的点让我不得不百度:1、金钱字段存储应当选择float、decimal、double?应当选择decimal。他是以字符串形式存储的,不会损失精度,为啥浮点型的(单精度、双精度)会损失精度呢,看下面的例子:定点数如果不写精度和标度,则按照默认值decimal(10,0)来操作,也就是存储11.1时候,会自
Stella981 Stella981
2年前
AS3 基本数据类型 primitive data type
int(带符号,32位整型,2147483648~2147483647),uint(无符号,32位整型,0~2147483647),Number(64位,双精度浮点型,1.79e308~5e324,0,5e324~1.79e308),String(UTF16,Unicode),Boolean(true/false)注意:
Wesley13 Wesley13
2年前
2.python内置数据结构
第一类:数值类型一.数值型包括1.int(整型):python3里数字不管多大永远都是int长整型,且没有大小限制,受限于内存区域的大小类型转换:int(x)返回一个整数2.float(浮点型):有整数部分和小数部分组成。支持十进制和科学计数法表示。只有双精度型类型转换:float(x)返回一个浮点数3.c
Wesley13 Wesley13
2年前
C语言32个关键字
C语言中有32个重要且比较常用的关键字,这里简单列举出来:C语言32个关键字第一类:数据类型关键字 A基本数据类型(5个)void声明函数无返回值或无参数,声明无类型指针,显式丢弃运算结果。char字符型类型数据,属于整型数据的一种。int整型数据,通常为编译器指定的机器字长。float单精度浮点型数据,属于浮点数