前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >避坑 | 记一次前端长整数精度丢失问题

避坑 | 记一次前端长整数精度丢失问题

作者头像
程序员鱼皮
发布2020-11-25 10:21:41
10.1K1
发布2020-11-25 10:21:41
举报
文章被收录于专栏:鱼皮客栈鱼皮客栈

前几天,鱼皮在工作时遇到一件很奇怪的事。

分享给大家,避坑避坑~

孽起

在前后端联调时,发现后端有一个接口返回的值和前端页面上展示的值不一致。

后端Java实现的接口如下,返回一个json格式的大整数 123456789123456789

代码语言:javascript
复制
@RestController
@RequestMapping("/test")
public class YupiTestController {

    @GetMapping
    public Long getNum() {
        return 123456789123456789L;
    }   
}

但是前端请求这个接口后,在界面上展示的却是 123456789123456780,最后一位是0而不是9!

问题定位

后端同学利用curl工具测试自己的接口,得到的数据完全正确。

前端同学打开浏览器的开发者工具(F12)查看网络请求(注意要查看请求原生的返回值,而不是被浏览器二次处理过的格式化数据),发现后端返回的数据完全正确。

既然后端数据返回正确,那就是前端的锅没跑了。

可是前端明明拿到后端返回的json数据,解析成数字就直接展示了,为什么最后一位数字展示错误呢?

发现元凶

比对分析接口返回和前端展示的数据,发现只有数字超过16位时,才会出现最后几位数字不一致的问题。

难道是数字太大了,发生了精度丢失?

Java语言中的Long类型是64位,难道前端Js语言的Long类型小于64位?

等等,Js好像没有Long类型!

那就百度一下Js的数字类型,终于发现了问题的元凶。

Js的Number类型

在Js中,用Number来表示数字类型的值。Number类型总长度64位二进制bit,使用53位表示小数位,10 位表示指数位,1 位表示符号位。因此,Number整数的表示范围为 -2^53 ~ 2^53(不包含两端)

可以在控制台打印Number的最大和最小值:

Number最大值

Number最小值

在其他语言,如Java中,Long类型占64位二进制bit,最大值为:9223372036854774807(2^63 - 1)长度约19位。

而在Js中,由于Number类型的值也包含了小数,最大值为:9007199254740993(2^53 - 1)长度约16位。

因此当Java返回超过16位的Long型字段转为json时,前端Js得到的数据将由于溢出而导致精度丢失。

既然知道了出现问题的原因,解决问题就很简单了。

如何解决?

虽然前端也可以解决问题,比如通过正则表达式解析替换、或者修改json parser,但比较麻烦,更推荐在后端解决

非常简单,将可能超出范围的数字类型(Long)变量转为字符串类型(String)即可!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-10-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员鱼皮 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 孽起
  • 问题定位
  • 发现元凶
  • Js的Number类型
  • 如何解决?
相关产品与服务
云开发 CLI 工具
云开发 CLI 工具(Cloudbase CLI Devtools,CCLID)是云开发官方指定的 CLI 工具,可以帮助开发者快速构建 Serverless 应用。CLI 工具提供能力包括文件储存的管理、云函数的部署、模板项目的创建、HTTP Service、静态网站托管等,您可以专注于编码,无需在平台中切换各类配置。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档