You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
number = (-1)^sign*M^E
javascript的浮点数遵守IEEE754规范。既然底数为52位,那么正整数的安全上界也很容易计算,即2^53-1。因为52个比特位全部是1表示的整数就是2^53-1。而这个数值其实在js中可以查到,为Number.MAX_SAFE_INTEGER。也就是小于等于这个整数是可以安全使用的,那么大于它会出现什么意外呢?
缘起
公司组织架构大规模调整,需要同步oa系统的架构到腾讯邮箱(后用exmail代替)上。为了减少手工劳作并造福后人,决定封装exmail的api并告成命令行工具。由于oa系统就是node全栈开发的,理所当然就用node来完成这个同步的工作。但是工作中遇到了奇怪的问题。
exmail的部门id大概有这么长
40066889765020778
,基本上可以确定对应数据库的bigint类型,为什么不是字符串?因为返回的json数据是不带引号的~这时出现了神奇的情况。看到了吗,id是一样的,这科学吗?显然不科学。思考3秒钟,以为是exmail接口的bug,于是问了他们的开发人员,他们说是不是整数越界引起的。我突然意识到很有道理呀,为什么不再多思考几秒(叹气)?
于是我直接打印出了http请求response的text,因为http通讯返回的都是字符串,转换成json的过程是应用层做的,也就是调用了JSON.parse方法。真相如下:
所以问题就出在js处理大整数的这个过程
分析
思考了一下node的number类型,虽然没有明显区分整数与浮点数,但v8肯定是有做优化的,否则计算效率不要慢死。再一想number类型是支持64位的,也就是无论整数还是浮点数都是64bit存储,既然node(javascript)语法层面没有显性定义整数和浮点数类型,那么整数的底层存储结构应该同浮点数一致。也就是大学计算机组成原理学过的:
![](https://camo.githubusercontent.com/55ab17af9dcd8d8337c7fc8bf69c763bee5b9b790d463f8a141ea40f09eb42ef/68747470733a2f2f75706c6f61642e77696b696d656469612e6f72672f77696b6970656469612f636f6d6d6f6e732f612f61392f494545455f3735345f446f75626c655f466c6f6174696e675f506f696e745f466f726d61742e737667)
number = (-1)^sign*M^E
javascript的浮点数遵守IEEE754规范。既然底数为52位,那么正整数的安全上界也很容易计算,即2^53-1。因为52个比特位全部是1表示的整数就是2^53-1。而这个数值其实在js中可以查到,为
Number.MAX_SAFE_INTEGER
。也就是小于等于这个整数是可以安全使用的,那么大于它会出现什么意外呢?我们发现+1和+2的结果是相同的,为什么呢?
解决
想到几种方案
最终,我用go完成了这个任务
The text was updated successfully, but these errors were encountered: