likes
comments
collection
share

解决前端精度丢失问题

作者站长头像
站长
· 阅读数 14

我正在参加「掘金·启航计划」

前言

前端的同学基本都遇到过,关于js精度丢失的问题; 比如: 后端给前端返回一个数字类型的id, 但是, 前端对这个id不做任何处理,直接使用到下一个给后端请求的时候, 接口报错了, 后端一查,说,你前端id给传错了,然后前端一看,果然是给传错了, 但是自己又没有做什么,怎么拿的就怎么给后端了。问题出在哪呢? 最后,才知道是因为 : 后端给的数字太大超过-9007199254740991 (-(2^53-1))9007199254740991(2^53-1)之间的整数,前端js这块就会自动四舍五入,导致精度丢失

解决前端精度丢失问题

再比如: 前端要进行大数字之间的运算,也会精度丢失。

可转成字符串

让后端把传过来的id转成字符串; 我司后端当时说他转成字符串了, 但是我这边拿着热乎的数据,检测了类型,是数字非字符串,当然精度依旧会丢失。 最后, 我让他直接简单粗暴加个双引号,我这边检测类型才是字符串, 也不知道为啥,是后端转的有问题还是什么原因。 当然,拿到字符串的id,再传给后端是没有问题的,精度就不会丢失

问题

前端大数字之间的运算,精度丢失问题无法解决;

BigInt

因为number的基本类型不能超过2^53,不然就会精度丢失为了解决这个限制,在ECMAScript标准中出现了BigInt

什么是?

BigInt可以表示任意大的整数;

创建

  1. 直接BigInt去创建; BigInt(value)

解决前端精度丢失问题

  1. 后面加个n就可

解决前端精度丢失问题

当然,此方式可以成功解决前端大数字之间运算的问题;

前端直接把热乎的id转成字符串也会精度丢失,但配合BigInt解决了此问题

有次,我是拿到后端给的number类型的id,明明拿着热乎的数据,直接String,转成字符串时,就已经精度丢失了; 于是,我用了第一种方式,让后端给我传过来时,就加双引号转成字符; 第二种方式就是我这边用了BigInt, 本来我以为我这边拿着热乎的id直接Sting一下, 然后传给后端,发现不行,精度也是丢失了,于是就这样: String(BigInt(result)); String配合BigInt, 就可以,解决精度丢失并顺利转成字符传给后端的问题;

结尾

上面,是我的项目中遇到跟后端合作时,前端大数据精度丢失的问题; 我是把后端Number类型的id通过String和BigInt转成字符串传给后端; 但是,咱们就技术而言,不论其他:(平常肯定都是推给后端,让后端转去), 如果后端要求给他传过去的id类型是Number呢,各位大佬可否知道,前端有没有什么好的方式解决呢?

注意:

前端直接这样写大数据转换不行:

let result=124569875984123677888999;  //估摸着这一步就在前端已经精度丢失了
String(BigInt(result));

let result=124569875984123677888999;这一步精度就可能已经丢失了;

下面这种也不行

let result=BigInt(124569875984123677888999);   //这里也已经精度丢失了
String(result);

因为在这一步,BigInt(124569875984123677888999); 你还没来的及转成BigInt,就已经精度丢失了;

下面这样就可以; 前端的大数据,可以在第一步就先给大数据后加n,直接写成BigInt类型的就可以;

let result=124569875984123677888999n; 
String(result);

因为你一开始在前端写的数据就是BigInt类型的,所以不会造成精度丢失问题;

解决前端精度丢失问题

文章上面我是直接拿后端返过来的number类型的大数据,然后直接String(BigInt(result))这样子再传给后端是可以的。 前端直接那样写的number类型大数据的话,一开始就可能会造成丢失精度, 除非可在前端大数据后面直接加n的方式,一开始就写成BigInt类型的也是可以的。

转载自:https://juejin.cn/post/7249288285809180709
评论
请登录