为什么 JavaScript 中的 0.3 + 0 == 0.3 和 0.1 + 0 == 0.1 不能完全用二进制表示

why 0.3 + 0 == 0.3 and 0.1 + 0 == 0.1 in javascript when 0.3 and 0.1 cannot be represented exactly in binary

提问人:runtimeerror 提问时间:2/14/2022 最后编辑:runtimeerror 更新时间:2/14/2022 访问量:778

问:

第一个问题: 如果我们这样做,在 java 脚本中。

0.2 + 0.1
=>0.30000000000000004

因为 0.2,0.1 四舍五入为不同的数字,总和也四舍五入为不同的数字 本文解释了幕后花絮。我明白这一点,但是 当我这样做时。

0.3 + 0
=>0.3  

它显示 0.3 为什么?0.3 不能完全用二进制表示,应该四舍五入到不同的数字,对吧?。
因此,0.3 + 0 的值应该是 0.3 的四舍五入数和总和(如果需要的话)。

第二个问题:
我们什么时候这样做。

let x = 0.3

由于 0.3 不能用二进制精确表示,它被四舍五入到另一个数字,但是当您访问变量 x 时,为什么它显示 0.3 而不是实际四舍五入的数字。

x
=>0.3

但是当你这样做时。

0.2 + 0.1
=>0.30000000000000004

它显示数字的实际舍入,但不是 0.3。 请解释。

JavaScript 浮点 精度 IEEE-754

评论

0赞 VLAZ 2/14/2022
"0.3 不能用二进制权利精确表示“,但并没有给你带来不同的东西(即使它不精确)。增加的额外零不会真正干扰已经存在的值。0.30.3
0赞 jsotola 2/14/2022
javascript 真的在 0.3 + 0 中执行加法吗?...也许它会使零短路
0赞 T.J. Crowder 2/14/2022
@jsotola - 是否执行操作并不重要,它不会影响为 存储的值。0.3
0赞 runtimeerror 2/14/2022
我在编辑时得到了答案。没想到会这么快。
0赞 T.J. Crowder 2/14/2022
@runtimeerror - :-) 所以是一个非常活跃的地方。

答:

5赞 T.J. Crowder 2/14/2022 #1

加法时得到的值和从文字中得到的值是不同的值(两者都不是正好 3/10,两者都非常接近)。(添加无关紧要,它不会更改要添加到的数字的值。你得到的那个刚刚超过3/10;你得到的那个(如果我没记错的话)不到 3/10。0.10.20.300.1 + 0.20.3

在将浮点数转换为文本时,JavaScript 遵循通常的做法,即仅包含所需的数字数,以将其与格式可以表示的下一个最接近的值区分开来(规范和规范引用的学术论文的详细信息)。 不需要任何额外的数字来区分,但确实如此(我猜要将其与 区分开来,但我实际上并不知道)。0.30.300000000000000040.3

评论

0赞 runtimeerror 2/14/2022
从这些文章中很难理解。目前,这些文章中有很多东西超出了我的知识范围。但如果有人能用简单的方式解释它,举个例子,一步一步地解释,我会很高兴。
0赞 T.J. Crowder 2/14/2022
@runtimeerror - 从字面上看,最基本的是,当你得到数字的字符串时,它并不完全是数字是什么。只需确保将字符串转换回数字即可获得相同的数字。 IIRC 是(或类似的东西),但由于这是您转换回数字时得到的,因此这是用于与人类交互的字符串。 之所以显示为 ,是因为它需要与 区分开来。"0.3"0.30.30.299999999999998"0.3"0.1 + 0.2"0.30000000000000004""0.3"
0赞 runtimeerror 2/14/2022
这样展示是不是错了。因为当您将 0.3 指定为文字但在引擎盖下时,它被存储为不同的数字。检索时,它不会显示实际存储的值。这让人们认为他们实际上存储了 0.3,但事实并非如此。这不会导致不必要的错误和混乱吗?
1赞 T.J. Crowder 2/14/2022
@runtimeerror - 高效的浮点数是精度、大小和运行时成本之间的折衷方案;更多内容请点击此处。是的,人们经常遇到麻烦,因为他们没有意识到他们使用的浮点数的局限性。值得庆幸的是,在当今世界,与定义 IEEE-754 binary64 格式时相比,内存和处理器速度得多,我们越来越多地获得其他选择(包括相对较新的 IEEE-754 decimal128)。JavaScript的...
1赞 T.J. Crowder 2/14/2022
...将很快获得某种十进制类型(C# 已经有一个)。同时,当 IEEE-754 binary64 没有您需要的精度(例如财务计算)时,您可以使用一些库。至于它是否具有误导性,这是一个价值判断,我不打算评论,只是说很多东西的设计和思考已经投入到这些东西的设计中——比如我上面引用的那篇论文。:-)