问题描述

对于json的数据如果不编排一下格式查看起来很费劲,比较流行的一款chrome/Firfox下处理json的插件JSON-handle。最近使用的时候发现一个问题,导致格式化后根据订单去页面中定位数据时查询不到,非常诡异。回想起前一段时间做功能的时候,在js中显示订单号时也出现过类似的问题,于是决定一探究竟。探究到最后发现是由于js中number的精度问题导致的。我在js中展示的时候由于数据类型是long,超过了js的精度,我就在后台多加了一个String类型的字段专门用来js展示订单号之用,这样解决了我的问题。详细原因,请看问题原因描述详解

参考文章:
http://www.heyuan110.com/2015/06/16/Chrome-FireFox%E5%A4%84%E7%90%86JSON%E7%9A%84%E6%8F%92%E4%BB%B6/
插件官网:
jsonhandle.sinaapp.com

问题原因描述详解

地址:
TB”>http://zhidao.baidu.com/link?url=vVCdzXTs5kTKykFkPuxdfcpS7umlMPejIBudaU9U51Us5SmMkc4aYQm4gGMj3dclM0IRnBzBAQFLdE6_tsKuAfiPDK_9Wg1XWtT8ri-TB
摘录:
JavaScript 中的数字是用”IEEE 754 双精度64 位浮点数”来存储的,

其格式为:

    s x m x 2^e

s 是符号位,表示正负。

m 是尾数,有 52 bits.

e 是指数,有 11 bits.

在 ECMAScript 规范 里有给出 e 的范围为 [-1074, 971].

Number.MAX_VALUE = 1 x (2^53 - 1) x 2^971 = 1.7976931348623157e+308

Number.MIN_VALUE = 1 x 1 x 2^(-1074) = 5e-324

//使用如下js查看Number.MAX_VALU与Number.MIN_VALUE
alert(Number.MAX_VALUE);
alert(Number.MIN_VALUE);

所以JS能存储的数值是非常大的。
但是使用如下测试语句:

var x = Math.pow(2, 53) - 10;
while (x != x + 1) x++;
alert(x);

结果看似死循环的程序,跳出了,x的最终结果为9007199254740992=2^53。
也就是说,
当 x 小于等于 2^53 时,可以确保 x 的精度不会丢失,
当 x 大于 2^53 时,x 的精度有可能会丢失。

//x2^53 + 1 时,其二进制表示为:
10000000000...001 (中间共有 520)
//用<a href="https://www.baidu.com/s?wd=%E5%8F%8C%E7%B2%BE%E5%BA%A6%E6%B5%AE%E7%82%B9%E6%95%B0&tn=44039180_cpr&fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1Y3nHu9rAFWP1I9mhFBPHN90ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1DknH0YPjfLPWcdnW0znHTvPHb" target="_blank" class="baidu-highlight">双精度浮点数</a>存储时:
e = 1; m = 10000..00(共 52 个 0,其中 1 是 hidden bit)

显然,这和 2^53 的存储是一样的。
按照上面的思路可以推出,
对于 2^53 + 2, 其二进制为 100000…0010(中间 51 个 0),也是可以精确存储的。
最后结论:
当 x 大于 2^53 且二进制有效位数大于 53 位时,就会存在精度丢失。

最后建议

个人还是感觉sublime比较好用,使用里面的Pretty JSON插件还是挺好用的。

GitHub 加速计划 / js / json
41.72 K
6.61 K
下载
适用于现代 C++ 的 JSON。
最近提交(Master分支:1 个月前 )
960b763e 3 个月前
8c391e04 6 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐