为什么浮点数尾数的位宽表示的数字是 int 的两倍?

dav*_*361 6 c++ floating-point mantissa

有人告诉我,doubleC++ 中的 a 有一个尾数,能够安全、准确地表示 [-(2 53 \xe2\x88\x92 1), 2 53 \xe2\x88\x92 1] 整数。

\n

当尾数只有 52 位时,这怎么可能呢?为什么 anint16只能具有 [-32,768, +32,767] 或 [-2 15 , 2 15 -1] 的范围,而同样的东西可以用来int16允许两倍的可表示数字?

\n

Cof*_*sso 7

(64位)的格式double如下:

1 bit: sign
11 bits: exponent
52 bits: mantissa
Run Code Online (Sandbox Code Playgroud)

我们只需要查看可以用尾数表示的正整数,因为符号位为我们处理负整数。

天真地,用 52 位,我们可以存储从 0 到 2^52 - 1 的无符号整数。使用符号位,这让我们可以存储从-2^52 - 12^52 - 1

不过,我们有一个可以使用的小技巧。我们说整数的第一个数字始终是1,这给了我们一个额外的位来使用。

为了了解其原理,让我们更深入地研究一下。

1每个正整数在其二进制表示中都至少有一个。因此,我们使用指数向左或向右移动尾数,直到开始时得到 1。一个例子可能会有所帮助:

9、表示为unsigned int:(000...0001001点代表多个0s)。

另一种写法:1.001 * 2^3. (1.001是二进制,不是十进制。)

而且,我们同意永远不使用 0 作为第一位。因此,即使我们可以将 9 写为0.1001 * 2^40.01001 * 2^5,但我们不会。我们同意,当我们以这种格式写出数字时,我们将始终确保使用指数来“移动”位,直到我们以 开头1

那么,我们需要存储获取的信息9如下:

e: 3
i: 1.001
Run Code Online (Sandbox Code Playgroud)

但如果i总是以 开头1,为什么每次都要写出来呢?让我们保留以下内容:

e: 3
i: 001
Run Code Online (Sandbox Code Playgroud)

正是利用这些信息,我们可以将数字重构为:1.i * 2^e == 9

当我们达到更大的数字时,我们的“ i”会更大,可能会使用最多 52 位,但我们实际上存储的是53信息位,因为1我们总是有前导。

最后注意:这并不完全是存储在双精度数的指数和尾数中的内容,我已经简化了一些内容以帮助解释,但希望这可以帮助人们理解丢失的位来自哪里。另外,这不包括0,它得到一个特殊的表示(上面使用的技巧不适用于0,因为 的通常表示中0没有任何1s )。