当许多人试图解释浮点数表示时,将其分解为三个部分:
我知道这些值在单个64位地址中被视为整数(对于双精度数)。我没有看到的解释是当计算机对小数点分隔符一无所知或者它应该在尾数中“放置”时,你如何用二进制格式表示1.2345的尾数。
我正在寻找一个完整的逐步解释,说明如何构造一个(如果你想要的话,32位)十进制数的浮点表示,反之亦然。
答案 0 :(得分:2)
以下假定采用二进制格式。
除少数特殊情况(0和次正规数)外,有效数 m (技术名称:a mantissa是一个类似但略有不同的概念)在区间内1≤ m < 2,因此不需要存储前导数字(因为它总是1)。
其余位给出小数部分,存储为二进制。您可以将此视为减去2的递减幂:
等。继续这个过程为您提供扩展
... 00111100000010000011000100100110111010010111100011010100111111
(来自Rick Regan's decimal/binary converter)
对于double,这会舍入为52位(如果计算隐式前导1,则为53):
0011110000001000001100010010011011101001011110001101
答案 1 :(得分:-1)
实际上,小数点不存储在数字的浮点数或双重表示中。你对浮点数表示的三个部分是正确的,但有一些重要的细微差别:
0
表示正值,1
表示否定。3
表示23
而不是103
。在32位浮点数的情况下,我们有8位指数,假设10000000
为零,这给出了-128到127之间的指数(我们可以将数字从2-128
编码为2127
使用它们。)[0, 1)
之间,或大于或等于0
且小于1
。这样我们就不必存储0.
部分,即0.1234
可以存储为1234
。现在,如何将上述内容存储在实际的浮点数中。我们来看看例如,我们有一个数字x = 123.456
。
为正,因此符号位为0.
现在我们查找y
- 2
的最小幂,以便0 <= x/y < 1
。在我们的例子中,它是128
(或27
):123.456 / 128 = 0.9645
,它使指数等于7
或00000111
二进制。
现在我们必须对0.9645
进行编码,但我们不需要实际存储0.
部分。正如您现在所知,数字的小数部分以二进制表示为从左侧开始计数的2的负幂,即二进制中的0.1101
表示1 * 2-1 + 1 * 2-2 + 0 * 2-3 + 1 * 2-4 = 1/2 + 1/4 + 0 + 1/16 = 0.5 + 0.25 + 0.0625 = 0.8125
。这就是我们将0.9645
转换为二进制的方法 - 我们递归地减去2的负幂,直到我们有0或用完比特(这是精度问题引发的地方):0.9645 - 2-1 - 2-2 - 2-3 - 2-4 - 2-6 - ...
或{{ 1}}二进制。展望未来,0.111101...
在基数2中为0.9645
,精度为23位(在我们将1作为符号,8作为指数后,这个位数被排除在32之外)。
总结,我们得到了我们的初始数字0.11110110111010010111100
:
0 00000111 11110110111010010111100 ^ ^ ^ | | | | | +--- significand = 0.9644999504089356 ~ 0.9645 | | | +------------------- exponent = 7 | +------------------------- sign = 0 (positive)