我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。我们似乎没有那样做。
答案 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中:
- 如果 m NaN ,请返回字符串“NaN”。
- 如果 m + 0 或 -0 ,请返回字符串“0”。
- 如果 m 小于零,则返回字符串“ - ”和ToString( - m )的字符串并置。
- 如果 m 为无穷大,请返回字符串“无限”。
- 否则,让 n , k 和 s 为整数,使k≥1,10 k-1 ≤s< 10 k ,s×10 n-k 的数值是 m , k 小到可能。请注意, k 是 s 的十进制表示中的位数, s 不能被10整除,并且最低有效位数 s 不一定由这些标准唯一确定。
- 如果 k ≤ n ≤21,则返回由 s的十进制表示的 k 数字组成的字符串
(按顺序,没有前导零),然后是 n-k 出现的字符'0'。- 如果0 < n≤21,返回由 s 的十进制表示的最重要 n 数字组成的字符串,后跟小数点'。 ,然后是 s 的十进制表示的剩余 k-n 数字。
- 如果-6&lt; n≤0,返回由字符'0'组成的字符串,后跟小数点'。',然后是 - n 次出现字符'0',后跟 s 的十进制表示的 k 数字。
- 否则,如果 k = 1,则返回由 s 的单个数字组成的字符串,后跟小写字符'e',然后是加号'+'或减号' - ',根据 n -1是正还是负,后跟小数表示整数abs( n -1)(没有前导零)。
- 返回由 s 的十进制表示的最高位数字组成的字符串,后跟小数点'。',然后是剩余的 k s 的十进制表示的-1位数,后跟小写字母'e',后跟加号'+'强>减号' - '根据 n -1是正还是负,后跟整数abs的十进制表示( n -1)(没有前导零)。
醇>
然后有以下注释;点击链接了解完整详情。注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是本文工作的主要动机。)