后台 long 类型在 js 中丢失精度的问题大家是怎么解决的?

2019-01-11 10:44:14 +08:00
 xiangyuecn

查了一下 JavaScript 能处理的最大整数为 Math.pow(2, 53) == 9007199254740992。9007199254740992+1 就开始不能正确表示了。

后端数据中有些 long 类型的数据(比如 id 生成器生成的 long 类型 id ),如果直接发数字给前端,就会出问题。

但一棍子打死全部 long 类型转成字符串好像也比较困难。想了一下,全转成字符串操作起来有点复杂,一不留神就会遗漏。而且因为 long 类型包含 int 类型范围,有可能因为测试值并未超过 js 的最大精度,漏转的地方会成为难以排查的隐藏 bug。

v 友们遇到过这种问题吗,要怎样方便的解决?

7813 次点击
所在节点    程序员
20 条回复
shapl
2019-01-11 10:53:09 +08:00
lzxz1234
2019-01-11 11:07:02 +08:00
一棍子打死全部 long 类型转成字符串好像也比较困难
找对地方,一点也不困难
wenzhoou
2019-01-11 11:07:30 +08:00
个人认为既然是 ID,你又不拿它做数字运算。那就应该定义成字符串类型。岂不妙哉。
66beta
2019-01-11 11:09:14 +08:00
同楼上,你是 ID,又不做运算,字符串有什么还担心的
VDimos
2019-01-11 11:15:52 +08:00
用第三方库
supuwoerc
2019-01-11 11:17:13 +08:00
不做运算直接 String 岂不妙哉
xiangyuecn
2019-01-11 11:17:55 +08:00
@66beta @wenzhoou
我也是这样想的,ID 这种处理起来比较简单。但 long 类型并不只是 id 会用到啊。可能某些计算结果也是 long 类型,如果忘记处理成 string,不就出乱子了么,而且忘记处理的有点难排查,因为测试时这个 long 值可能比较小,测试时不会出问题,就埋了个雷。

@lzxz1234 #2 这个地方难找,昨晚想了一晚上 还失眠了
xiangyuecn
2019-01-11 11:20:30 +08:00
@shapl 厉害了这个 js 库,拿来用了
lzxz1234
2019-01-11 11:23:26 +08:00
你要把数据返给前端,肯定有个地方进行序列化吧,可能是模板可能是 json,在这定制个规则加上引号就行了
wenzhoou
2019-01-11 11:29:03 +08:00
非 ID 的话。具体问题具体分析吧。

a 系统和 b 系统的数值范围不一致,这很正常。前端到后台,后台到数据库和别的系统,数值不一致这种事情多了。

你把前端的取值范围调大了。前端的数据往后台系统传的时候,也有可能越界啊。

不过,你把后台系统的 long 型定为标准,原则上也是没有问题的。

问题能解决就好。
lolizeppelin
2019-01-11 11:33:02 +08:00
用 jsonlint 加 long.js 解决

这样 json 解析的时候 超过长度的会返回的就是一个 Long 对象

数字处理会方便点...
xiangyuecn
2019-01-11 11:41:24 +08:00
@lzxz1234 嗯,json 数据 我研究一下是后端处理简单还是前端处理简单
lolizeppelin
2019-01-11 11:43:18 +08:00
随便看了下 1 楼的库, 就代码行数上来看太简单了很有可能 json 解析并不靠谱

应该不如 jsonlint

虽然我都没认真读过里面代码, 但是 jsonlint 原理上屌不少 23333
brucewuio
2019-01-11 13:46:10 +08:00
分开咯 比如 2 个 int 自己写个能满需求的
zouqiang
2019-01-11 15:50:40 +08:00
json 序列化的时候转 string
DOLLOR
2019-01-11 16:18:59 +08:00
https://github.com/MikeMcl?tab=repositories
这位仁兄写的几个 2K+Stars 工具都挺不错的,可以操作大数字,可以选一个试试。
vigossliao
2019-01-11 17:27:47 +08:00
这些工具库还是没有解决掉本质的问题

而且忘记处理的有点难排查,因为测试时这个 long 值可能比较小,测试时不会出问题,就埋了个雷。


某个字段可能出现 但是没有处理 或者 忘记处理了 或者 不知道那个字段会出现这个问题

就算前端有各种工具库来处理都是无济于事
除非前端在涉及到 number 的时候都用工具库来处理
LeoEatle
2019-01-11 22:53:26 +08:00
先考虑这个数据是用作什么的,id 的话完全可以转字符串
zzjas98
2019-01-12 03:56:49 +08:00
最近 Chrome 出了一个对 BigInt 的 type 的支持。是作为浏览器内的 primitive type 支持的,应该效果不错。但是跨浏览器原生支持好像还不是很全。

> BigInts are a new numeric primitive in JavaScript that can represent integers with arbitrary precision.

想了解的话可以看看这些链接
Spec: https://tc39.github.io/proposal-bigint/
Coverage: https://caniuse.com/#search=bigint
Chrome Implementation: https://developers.google.com/web/updates/2018/05/bigint

总而言之是个挺新的东西,不一定现在有用,但是楼主不妨了解一下没准过段时间就能广泛使用了。
q540374501
2019-11-23 20:32:06 +08:00
bigint 没用啊,我要把 objectId 当做 bitmap 来用,加个 n,redis 根本不认识我靠

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/525937

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX