请参阅此代码:

<html>
  <head> 
    <script src="http://www.json.org/json2.js" type="text/javascript"></script>
    <script type="text/javascript">

      var jsonString = '{"id":714341252076979033,"type":"FUZZY"}';
      var jsonParsed = JSON.parse(jsonString);
      console.log(jsonString, jsonParsed);

    </script>
  </head>
  <body>
  </body>
</html>

当我看到我在Firefox 3.5控制台,jsonParsed的值是:

Object id=714341252076979100 type=FUZZY

即数量是圆形的。尝试了不同的值,相同的结果(数四舍五入)。

我还没有得到它的四舍五入规则。 714341252076979136四舍五入为714341252076979200,而714341252076979135四舍五入为714341252076979100。

修改查看下面第一评论。显然,这是不是JSON,但一些关于JavaScript号处理。但问题仍然是:

这是为什么?

有帮助吗?

解决方案

什么你在这里看到的实际上是两个倒圆的效果。 ECMAScript中号码在内部表示双精度浮点。当id设为714341252076979033(十六进制0x9e9d9958274c359),它实际上被分配最接近的可表示的双精度值,这是7143412520769790720x9e9d9958274c380)。当打印出来的值,它被舍入到15个显著十进制数字,这给14341252076979100

其他提示

您正在溢出JavaScript的号码类型的能力,看到§有关详细信息,规范 8.5。这些ID将需要的字符串。

IEEE-754双精度浮点(种类号的JavaScript用途)不能精确地表示所有(当然)号码。有名,0.1 + 0.2 == 0.3是假的。这会影响整个数字,就像影响分数;它开始,一旦你得到上述9,007,199,254,740,991(Number.MAX_SAFE_INTEGER)。

除了Number.MAX_SAFE_INTEGER + 19007199254740992)时,IEEE-754浮点数格式可以不再代表每个连续整数。 9007199254740991 + 19007199254740992,但9007199254740992 + 1同时 9007199254740992因为9007199254740993不能在格式来表示。能够成为下一个是9007199254740994。然后9007199254740995无法进行,但9007199254740996即可。

原因是我们的比特用完,所以我们不再有1秒的位;最低阶位现在代表的2的倍数。最终,如果我们坚持下去,我们就失去该位,只工作4的倍数等等。

您的值是以及高于阈值,并且使他们获得四舍五入到最接近的表示值。


如果你好奇的位,这里发生的事情:一个IEEE-754二进制双精度浮点数有一个符号位,指数为11位(其中,规定数量的整体规模作为动力的2,因为这是一个二进制格式]),并且有效数位52(但格式是如此聪明它得到的精度53位掉那些52个比特)。如何使用该指数是复杂的(此处描述的),但是在<强>非常模糊的条款,如果我们增加一个指数,有效数的值加倍,因为指数是用于2的幂(再次告诫在那里,它不是直接的,有聪明在那里)。

因此,让我们看看值9007199254740991(又名,Number.MAX_SAFE_INTEGER):

   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− sign bit
  / +−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− exponent
 / /        |  +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+− significand
/ /         | /                                                  |
0 10000110011 1111111111111111111111111111111111111111111111111111
                = 9007199254740991 (Number.MAX_SAFE_INTEGER)

这指数值,10000110011,意味着每一个我们添加一个到有效数时,数字表示由1上升(整数1,我们输给早得多表示小数的能力)。

但现在,有效数已满。走过去的这个数字,我们要增加的指数,这意味着如果我们添加一个有效数字,代表数的值由2上升,而不是1(因为指数应用于2,在此基础二进制浮点数):

   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− sign bit
  / +−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− exponent
 / /        |  +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+− significand
/ /         | /                                                  |
0 10000110100 0000000000000000000000000000000000000000000000000000
                = 9007199254740992 (Number.MAX_SAFE_INTEGER + 1)

好了,那也没关系,因为9007199254740991 + 19007199254740992反正。但!我们不能代表9007199254740993。我们位用完。如果我们增加仅1到有效数,它增加了2到值:

   +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− sign bit
  / +−−−−−−−+−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− exponent
 / /        |  +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+− significand
/ /         | /                                                  |
0 10000110100 0000000000000000000000000000000000000000000000000001
                = 9007199254740994 (Number.MAX_SAFE_INTEGER + 3)

格式只是不能代表奇数了,因为我们增加值,指数太大。

最后,我们有效数位的重新运行并有增加的指数,所以我们最终仅能够表示的4。然后的8。然后16.等等倍数倍数倍数。

它不受此JSON分析器引起的。刚刚尝试进入714341252076979033到fbug的控制台。你会看到同样714341252076979100。

请参阅此博客张贴的详细信息: http://www.exploringbinary.com/print-precision -of-浮点整数-变化太

JavaScript使用双精度浮点值,即一个53位总精度,但需要

ceil(lb 714341252076979033) = 60

位准确地表示的值。

最近的精确表示数为714341252076979072(写原数以二进制,替换最后7位与0和圆,因为最高的取代位是1)。

您会得到的,而不是这个数字,因为714341252076979100由ECMA-262描述ToString(),§9.8.1作品十的权力,并在53位精度所有这些数字都是平等的。

的问题是,你的电话号码需要更大的精度比JavaScript有

您可以发送一个字符串是多少?在两个部分分开?

JavaScript的只能处理精确的全数字高达9000亿美元(这是9 15个零)。高于,你会得到垃圾。通过使用字符串来保存的数字解决这个问题。如果你需要做数学与这些数字,编写自己的函数或者看看你是否能为他们找到一个库:我认为前,因为我不喜欢我见过的图书馆。为了让您一开始,看到我的两个功能在另一个答案

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top