我听说C++中的double
有一个尾数,能够安全准确地表示[-(253−1(,253−1]整数。
当尾数只有52位时,这怎么可能呢?为什么int16
只能具有[-32768,+32767]或[-215,225-1]的范围,而int16
可以使用相同的东西来允许两倍多的可表示数?
double
(64位(的格式如下:
1 bit: sign
11 bits: exponent
52 bits: mantissa
我们只需要看看我们可以用尾数表示的正整数,因为符号位为我们处理负整数。
简单地说,使用52位,我们可以存储从0到2^52-1的无符号整数。通过一个符号位,我们可以存储从-2^52 - 1
到2^52 - 1
的内容。
然而,我们有一个小技巧可以使用。我们说整数的第一个数字是总是一个1,这给了我们一个额外的比特。
要了解为什么这样做有效,让我们深入了解一下。
每个正整数在其二进制表示中将至少有一个1
。所以,我们向左或向右移动尾数,直到开始时使用指数得到1。这里有一个例子可能会有所帮助:
9,表示为无符号int:000...0001001
(表示更多0
s的点(。
另一种写法:1.001 * 2^3
。(1.001
是二进制的,而不是十进制的。(
而且,我们同意永远不要使用0作为第一位。所以,即使我们可以把9写成0.1001 * 2^4
或0.01001 * 2^5
,我们也不会。我们一致认为,当我们以这种格式写出数字时,我们将始终确保使用指数来";移位";直到我们从CCD_ 14开始。
因此,我们需要存储以下信息才能获得9
:
e: 3
i: 1.001
但是,如果i
总是以1
开头,为什么每次都要把它写出来呢?让我们只保留以下内容:
e: 3
i: 001
正是利用这些信息,我们可以将数字重建为:1.i * 2^e == 9
。
当我们达到更大的数字时;CCD_ 19";会更大,可能最多使用52位,但我们实际上存储的是53
位的信息,因为我们一直拥有领先的1
。
最后一点:这不是完全双精度的指数和尾数中存储的内容,我简化了一些内容来帮助解释,但希望这能帮助人们理解缺失的部分来自哪里。此外,这还不包括获得特殊表示的0
(上面使用的技巧对0
不起作用,因为0
的通常表示中没有任何1
s(。