javascript如何以这样的准确度打印0.1?

时间:2015-02-13 07:46:23

标签: javascript floating-point ieee-754

heard javascript数字是IEEE 754浮点数,这就解释了为什么

> 0.3 - 0.2
0.09999999999999998

但我不明白

> 0.1
0.1

我认为0.1不能准确地存储为基础2浮点,但它会向后打印,就像它一直是0.1。是什么赋予了?解释器在打印之前是否进行了一些舍入?

至少有两个版本的IEEE 754:1984版本和2008并没有帮助我。听起来后者添加了full support for decimal arithmetic。我们似乎没有那样做。

1 个答案:

答案 0 :(得分:10)

JavaScript使用IEEE-754双精度数字(“binary64”作为2008规范的说法;就像您所怀疑的那样,它是基础2版本,而不是2008年基础10版本。)

即使"0.1"无法在二进制64中完美呈现,您获得数字值0.1的字符串0.1的原因是 -

TL; DR :字符串不是该数字的精确版本,它恰好足以将其与其邻近区分开来。确切的数字

- 规范定义了将数字转换为字符串的复杂规则,以解决缺乏精确性的问题。它们包含在§9.8.1 - ToString Applied to the Number Type中:

  
      
  1. 如果 m NaN ,请返回字符串“NaN”
  2.   
  3. 如果 m + 0 -0 ,请返回字符串“0”
  4.   
  5. 如果 m 小于零,则返回字符串“ - ”和ToString( - m )的字符串并置。
  6.   
  7. 如果 m 为无穷大,请返回字符串“无限”
  8.   
  9. 否则,让 n k s 为整数,使k≥1,10 k-1 ≤s< 10 k ,s×10 n-k 的数值是 m k 小到可能。请注意, k s 的十进制表示中的位数, s 不能被10整除,并且最低有效位数 s 不一定由这些标准唯一确定。
  10.   
  11. 如果 k n ≤21,则返回由 s的十进制表示的 k 数字组成的字符串
  12. (按顺序,没有前导零),然后是 n-k 出现的字符'0'。   
  13. 如果0 < n≤21,返回由 s 的十进制表示的最重要 n 数字组成的字符串,后跟小数点'。 ,然后是 s 的十进制表示的剩余 k-n 数字。
  14.   
  15. 如果-6&lt; n≤0,返回由字符'0'组成的字符串,后跟小数点'。',然后是 - n 次出现字符'0',后跟 s 的十进制表示的 k 数字。
  16.   
  17. 否则,如果 k = 1,则返回由 s 的单个数字组成的字符串,后跟小写字符'e',然后是加号'+'或减号' - ',根据 n -1是正还是负,后跟小数表示整数abs( n -1)(没有前导零)。
  18.   
  19. 返回由 s 的十进制表示的最高位数字组成的字符串,后跟小数点'。',然后是剩余的 k s 的十进制表示的-1位数,后跟小写字母'e',后跟加号'+'减号' - '根据 n -1是正还是负,后跟整数abs的十进制表示( n -1)(没有前导零)。
  20.   

然后有以下注释;点击链接了解完整详情。注3可能是最相关的:

  

注3

     

ECMAScript的实施者可能会发现David M. Gay为浮点数的二进制到十进制转换编写的论文和代码很有用:

     

Gay,David M.正确地回合二进制 - 十进制和十进制 - 二进制转换。数值分析,手稿90-10。 AT&amp; T贝尔实验室(新泽西州默里山)。 1990年11月30日。可用   http://cm.bell-labs.com/cm/cs/doc/90/4-10.ps.gz。相关代码可用   http://cm.bell-labs.com/netlib/fp/dtoa.c.gz和   http://cm.bell-labs.com/netlib/fp/g_fmt.c.gz也可以在各种netlib镜像站点找到。

对我来说,4-10.ps.gz文件似乎已损坏(无法阅读第6-8页),但我在这里找到了一个PDF:http://ampl.com/REFS/rounding.pdf(不是随机的链接,因为它可能看起来,显然AMPL是本文工作的主要动机。)