javascript - JS用什么技巧显示/计算 float

标签 javascript floating-point

是的,我对 IEEE float 了如指掌。

例如,在二进制 float 学中没有精确表示十进制值 0.1

既然如此,使用了哪些技巧来“舍入”表达式的结果:

console.log(0.1 * 10)

恰好 1(即 (0.1 * 10) === 1 true) 时,如果我使用加法进行自己的计算:

console.log([...Array(10)].reduce((a) => a + 0.1, 0))

结果是(在我的机器上)0.9999999999999999

Javascript(以及很可能是其他运行时)如何捏造乘法以给出(直观的)正确答案,而不会陷入我手动执行此操作时遇到的相同问题?

最佳答案

  1 23456789012345678901234              bit #
  1.10011001100110011001101 * 0.0001     decimal 0.1
x                      1010              decimal 10
---------------------------
         
   1111 1111111111111111111              carries                      
   0011.0011001100110011001101 * 0.0001  1.10011001100110011001101 * binary 10
+  1100.11001100110011001101   * 0.0001  1.10011001100110011001101 * binary 1000
------------------------------
  10000.0000000000000000000001 * 0.0001  = 1 *trailing 1 dropped per LGRS
  12345 6789012345678901234
                          LGRS           LSb Guard Round Sticky
                          0001           ==>round down

顺便说一句,0.999999... == 1(“这在 Knuth 的《计算机编程艺术》一书中有证明)。但是,你是对的,将 10 个数字相加得到不同的结果,它不是 1.000。 .., 0.999..., 也不是 0.9999999999999999(所有非整数 float 都以 5 作为小数点右边最后一个非零数字),它是:

>>> print("%100.100f\n") % (0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1)
0.9999999999999998889776975374843459576368331909179687500000000000000000000000000000000000000000000000

有人建议我解释一下上面的总和,这是一个很好的建议。 我怀疑“证明”隐藏在“每个计算机科学家应该了解的浮点运算知识”(https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html#932) 中——“必读”。因此,我将把费力的手动验证作为练习留给提问者。为了提供帮助,这里是 LGRS 的真值表:

"first" bit
v
v
v     "last" bit (once set to 1, it NEVER shifts out to 0)
v     v
v     v
L G R S  Round (G, R, and S bits are not in final result)
0 0 0 0  down (means leave L bit as is)
0 0 0 1  down
0 0 1 0  down
0 0 1 1  down
0 1 0 0  down
0 1 0 1  up (means add 1 to L bit)
0 1 1 0  up
0 1 1 1  up
1 0 0 0  down
1 0 0 1  down
1 0 1 0  down
1 0 1 1  down
1 1 0 0  up
1 1 0 1  up
1 1 1 0  up
1 1 1 1  up

(不是“证明”)因为在添加 S==0 时,上面显示有 5 个下降 vs 3 个上升。此外,由于 1s 的密度约为 50%,预期结果可能会遍历整个真值表的这 1/2。因此,幅度的损失是有道理的。当有一个棘手的问题时,赔率会持平,或者可能会以另一种方式叠加。

关于javascript - JS用什么技巧显示/计算 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68482867/

相关文章:

javascript - Angularjs Route中的外部 View html文件

javascript - 只有第一个打开引导模式的按钮在 while 循环中起作用

casting - 所有 32 位 float 都精确表示为 f64 吗?

javascript - 3 乘以 1.1 时出现奇怪的结果

javascript - 检查 javascript 包含文件中的错误并解决该问题

Javascript:onclick 处理程序无法从 <a> 标记获取 'value' 属性

javascript - 尝试在 Javascript 中连接二维数组

C++ 精度 : String to Double

c - 为什么 printf 会四舍五入?

将二进制转换为 float