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

标签 javascript floating-point precision

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

最佳答案

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

JavaScript 对其 Number 类型使用 IEEE-754 基本 64 位二进制 float 。使用 IEEE-754,.1 + .2 的结果正好是 0.3000000000000000444089209850062616169452667236328125。这源于:

  • 将“.1”转换为可在 Number 类型中表示的最接近的值。
  • 将“.2”转换为可在 Number 类型中表示的最接近的值。
  • 将上述两个值相加并将结果四舍五入为最接近的 Number 类型可表示的值。

当格​​式化此 Number 值以供显示时,“0.30000000000000004”具有足够的有效数字来唯一区分该值。要看到这一点,请观察相邻值是:

  • 0.299999999999999988897769753748434595763683319091796875,
  • 0.3000000000000000444089209850062616169452667236328125,以及
  • 0.300000000000000099920072216264088638126850128173828125

如果转换为十进制数字只产生“0.3000000000000000”,则它更接近于 0.299999999999999988897769753748434595763683319091796875 而不是 0.3000000000000000444089 209850062616169452667236328125。因此,需要另一个数字。当我们有那个数字“0.30000000000000004”时,结果比它的任何一个邻居更接近 0.3000000000000000444089209850062616169452667236328125。因此,“0.30000000000000004”是最短的十进制数字(为了美观而忽略前导“0”),它可以唯一区分原始值是哪个可能的 Number 值。

此规则来自 ECMAScript 2017 语言规范第 7.1.12.1 条中的第 5 步,这是将 Numberm 转换为小数的步骤之一ToString 操作的数字:

Otherwise, let n, k, and s be integers such that k ≥ 1, 10k‐1s < 10k, the Number value for s × 10nk is m, and k is as small as possible.

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

关于javascript - 在格式化浮点值时,JavaScript 如何确定要生成的位数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49384477/

相关文章:

javascript - Firebase 限制在没有用户登录的情况下访问其他页面

javascript - 我在 JS DOM 中的表单验证有问题

javascript - 定义 popper 选项的问题

python - 将 x 浮点舍入为 y,并减少尾数(有效) float

python - 将 float 转换为 int 截断 rest,似乎不可靠

c++ - 如何将浮点值移位到可以精确表示的特定小数位数的最接近的值?

format - 如何在 IJulia 中选择数字输出格式?

javascript - 如何在 Rails 中格式化电话号码?

math - float 学有问题吗?

c++ - 启用矢量化后结果(略有)不同