计算机是先对运算中的数字进行舍入还是对结果进行舍入?

Does computer rounds the numbers in an operation first or round the result?

例如,在运算 9.4 - 9.0 - 0.4 中:计算机是先对每个数字进行舍入并存储,还是在一些额外位的帮助下进行计算(此示例采用双精度格式)然后进行舍入结果?这些是存储的值,但不确定如何手动进行此操作以检查它是否首先舍入每个数字。

二进制(9.4)= 0 10000000010 0010110011001100110011001100110011001100110011001101

二进制(-9.0) = 1 10000000010 0010000000000000000000000000000000000000000000000000

二进制(-0.4) = 1 01111111101 1001100110011001100110011001100110011001100110011010

二进制(9.4 - 9.0 - 0.4)= 0 01111001100 00000000000000000000000000000000000000000000000000000

一些程序或一些机器可能对中间结果使用额外的精度。这取决于很多因素:可用的硬件、您使用的编程语言、您使用的编译器、您传递给编译器的选项等。例如,为 Intel CPU 编译的程序有时可能如果中间结果被编译为使用 x87 instructions.

,则对中间结果使用 80 位精度

对于其余的答案,我假设所有操作都是在 64 位 "double precision" 浮点数中完成的。

每个数字先四舍五入,结果也四舍五入。例如 9.4 不能精确表示为二进制浮点数,因此程序中的 9.4 四舍五入为最接近的浮点数 。使用 64 位精度浮点数,该数字的精确数学值为:

9.4000000000000003552713678800500929355621337890625

所以 9.4 是 "rounded" 到 9.4000000000000003552713678800500929355621337890625。

同样,0.4也不能准确表示。这是"rounded"到:

0.40000000000000002220446049250313080847263336181640625

计算结果可能也需要四舍五入。两个 N 位数字相乘产生一个有 2N 位数字的数字。如果你只能存储 N 个数字,那么剩下的数字会发生什么?它们四舍五入。

这里你问的是减法。对于不同大小的数字,减法的结果必须四舍五入。在 (9.4 - 9) - 0.4 的特殊情况下,所有数字都具有相同的大小,因此不会发生四舍五入的情况,并且操作在数学上是精确的:

假设所有数字都保留为 64 位浮点数,第一个减法计算:

9.4000000000000003552713678800500929355621337890625 - 9.0 =
0.4000000000000003552713678800500929355621337890625

第二次减法计算:

  0.4000000000000003552713678800500929355621337890625 
- 0.40000000000000002220446049250313080847263336181640625
----------------------------------------------------------
  0.00000000000000033306690738754696212708950042724609375

一般情况下,计算机会将9.4 - 9.0 - 0.4中的数字转换为内部形式的数字,然后进行算术运算。这些转换通常会对其结果进行四舍五入。

考虑源代码中的文本 9.4 - 9.0 - 0.4。里面什么都没有数字。该文本是由字符组成的字符串。它包含字符“9”、“.”、“4”、“”、“-”等。通常,计算机会将此文本转换为其他形式进行处理。您可以编写处理文本格式数字的软件,但这种情况很少见。通常,当我们使用一种编程语言时,无论是编译型还是解释型,本文中的数字都会被转换成某种内部形式。 (“数字”是代表数字的一系列符号。因此“9.4”是代表 9.4 的数字。)

IEEE-754 binary64 是一种非常常见的浮点格式。在这种格式中,每个可表示的数字都以 2 的某个幂为单位表示。例如,数字 .125、.250、.375 和 .500 也是可表示的,因为它们是 1/8 的倍数,即 2−3。但是9.4不是2的任意幂的倍数,所以不能用IEEE-754 binary64来表示。

9.4转换为binary64时,最接近的可表示值为9.4000000000000003552713678800500929355621337890625。 (这是 2−50 的倍数,表示 9.4 附近的数字时使用的 2 的幂,特别是从 8 [含] 到 16 [不含] 的数字。)

9 可以用 binary64 表示,因此 9 转换为 9。

0.4 无法用 binary64 表示。当 0.4 转换为 binary64 时,最接近的可表示值是 0.40000000000000002220446049250313080847263336181640625。这是 2−54 的倍数,它是 2 的幂,用于从 ¼ 到 ½ 的数字。

9.4 - 9.0 - 0.4中,第一次减法的结果是0.4000000000000003552713678800500929355621337890625。这是完全可以表示的,所以此时没有四舍五入。然后,减去0.4,转换为上面的值后,得到0.00000000000000033306690738754696212708950042724609375。这也是可以精确表示的,因此此时也没有四舍五入。

上面描述了如果全程使用binary64会发生什么。许多编程语言或它们的特定实现都使用 binary64。有些可能使用其他格式。一些语言允许实现使用多种格式的混合——它们可能使用比 binary64 更广泛的格式进行计算,并转换为 binary64 以获得最终结果。这可能会导致您看到与上述不同的结果。

所以你的问题的答案是,使用浮点运算,each 操作产生的结果等于你通过计算确切的实数得到的数字数字结果,然后将该实数结果四舍五入为浮点格式可表示的最接近的值。 (四舍五入通常是通过四舍五入到最接近的可表示值来完成的,并通过几种方法之一解决关系,但其他舍入选择也是可能的,例如向下舍入。)

这些操作通常不会对其操作数进行舍入。 (也有例外,例如某些处理器可能会将次正规输入转换为零。)但是,必须首先生成这些操作数,例如将源文本转换为可表示的数字。这些转换是与减法或后面的其他操作分开的操作。