JavaScript类型精度丢失问题

296 阅读2分钟

Java Long类型字段作为Response返回时给前端时会存在精度丢失的情况

现象:

在做ES查询接口调试的过程中,后端返回了某id字段,类型为Long类型,value为746733131538423809。在Postman中调试返回的response中始终只能看到746733131538423800。最后两位精度始终丢失

原因:

Java Long类型和JavaSrcipt中的数字类型的精度范围不一致。

JavaScript内部只有一种数字类型Number,所有数字采用IEEE 754 标准定义的双精度64位格式存储,即使整数也是如此。

image-20220907171311735.png

含义如下:

  • 1位(s) 用来表示符号位,0表示正数,1表示负数
  • 11位(e) 用来表示指数部分
  • 52位(f) 表示小数部分(即有效数字)

因为小数部分最大是52位,因此JavaScript中能精准表示的最大整数是2^53-1,十进制为9007199254740991

不在这个范围的数叫做不安全整数不安全整数可能会导致精度丢失

console.log(Number.MAX_SAFE_INTEGER + 1);   // 结果:9007199254740992,精度未丢失
console.log(Number.MAX_SAFE_INTEGER + 2);   // 结果:9007199254740992,精度丢失
console.log(Number.MAX_SAFE_INTEGER + 3);   // 结果:9007199254740994,精度未丢失
console.log(Number.MAX_SAFE_INTEGER + 4);   // 结果:9007199254740996,精度丢失
console.log(Number.MAX_SAFE_INTEGER + 5);   // 结果:9007199254740996,精度未丢失

而我之前传的值746733131538423809已经远远大于了Number.MAX_SAFE_INTEGER,只要超过Number.MAX_SAFE_INTEGER,就有可能产生精度丢失,从而导致数据和逻辑出错的情况。

后端开发人员应该怎么做?

在给出到前端的锲约中,不要给Long类型的字段,可以用String代替。