在格式化浮点值时,JavaScript如何确定要生成的位数?

在格式化浮点值时,JavaScript如何确定要生成的位数?,javascript,floating-point,precision,Javascript,Floating Point,Precision,在JavaScript中,每个人都知道一个著名的计算:0.1+0.2=0.300000000004。但是为什么JavaScript打印这个值而不是打印更精确的0.30000000000444089298085006?当将数字值转换为十进制数字时,JavaScript的默认规则是使用刚好足够的数字来区分数字值。(您可以使用toPrecision方法请求更多或更少的数字。) JavaScript使用IEEE-754基本64位二进制浮点作为其Number类型。使用IEEE-754,.1+.2的结果正好

在JavaScript中,每个人都知道一个著名的计算:
0.1+0.2=0.300000000004
。但是为什么JavaScript打印这个值而不是打印更精确的
0.30000000000444089298085006

当将
数字
值转换为十进制数字时,JavaScript的默认规则是使用刚好足够的数字来区分
数字
值。(您可以使用
toPrecision
方法请求更多或更少的数字。)

JavaScript使用IEEE-754基本64位二进制浮点作为其
Number
类型。使用IEEE-754,
.1+.2
的结果正好是0.3000000000000000044408929098500626169452667236328125。这是由于:

  • 将“.1”转换为可在
    数字中表示的最接近的值
  • 将“.2”转换为可在
    Number
    类型中表示的最近值
  • 将上述两个值相加,并将结果四舍五入到可在
    数字中表示的最接近的值
格式化此
数字
值以供显示时,“0.300000000000000004”的有效位数刚好足以唯一区分该值。要查看这一点,请注意相邻值为:

  • 0.29999999999988897769753748434595763683319091796875
  • 0.30000000000444089209898500626169452667236328125
    ,以及
  • 0.30000000000999200707216264088638126850128173828125
如果转换为十进制数字仅产生“0.30000000000000000”,则它将更接近于0.299999999998889776975374345957683319091796875,而不是0.3000000000044408909098500626169452667236328125。因此,需要另一个数字。当我们有这个数字“0.300000000000000004”时,结果接近于0.3000000000044408929898500626169452667236328125,而不是它的任何一个邻居。因此,“0.300000000000000004”是最短的十进制数字(出于美观目的,忽略前导的“0”),它唯一地区分了原始值可能是哪个值

此规则来自ECMAScript 2017语言规范第7.1.12.1条中的步骤5,这是将
数字
值m转换为十进制数字以进行
ToString
操作的步骤之一:

否则,设n,k,s为整数,使得k≥ 1,10k-1≤ s<10k,s×10n-k的数值为m,k尽可能小


这里的措辞有点不准确。我花了一段时间才弄明白,通过“s×10n-k的数值”,标准指的是将数学值s×10n-k转换为
数值
类型(通常四舍五入)后的
数值。在这个描述中,k是将要使用的有效位数,这个步骤告诉我们要最小化k,所以它说要使用最小的位数,这样我们生成的数字在转换回
数字
类型时,生成原始数字m。

可能重复@SulthanAllaudeen我知道结果,但我不知道为什么js不打印完整的小数,而只保留17个小数?@SulthanAllaudeen:这不是该问题的重复。关于浮点算术如何工作的一般信息并不能回答将浮点值转换为十进制字符串时JavaScript如何格式化数字的问题。不同的语言会做出不同的选择(例如,固定数量的有效数字、唯一区分值所需的最少有效数字、显示准确值所需的位数)。这个问题应该通过解释JavaScript(ECMAScript)规范对此的说明来回答。感谢您的详细回答。您认为Js会使用toString方法格式化这个数值以显示,对吗?@GuangLin:我相信是这样,但我对ECMAScript规范没有经验。我模模糊糊地记得在我之前看的时候看到过这样的东西,但是我必须检查一下。非常感谢。如果你有一些新发现,请再次评论,让更多的程序员知道这个问题。