32 位 IEEE 754 单精度浮点到十六进制
32-bit IEEE 754 single precision floating point to hexadecimal
我学会了如何将数字转换为浮点数(在二进制、八进制和十六进制之上),并且知道如何将数字转换为浮点数。
但是,在查看给我的工作表时,我遇到了以下问题:
使用 32 位 IEEE 754 单精度浮点数以十六进制表示 -12.13。
我已经尝试查看我拥有的资源,但仍然无法弄清楚如何回答上述问题。给出的答案是0xc142147b.
编辑:抱歉没有澄清,但我想知道如何手动完成而不是编码。
-12.13
必须先转二进制再转十六进制。让我们或多或少像 glibc 库那样做,只使用笔和纸以及 Windows 计算器。
删除标志,但记住我们有一个:12.13
有效数(或尾数)
整数部分,12
很简单:C
(十六进制)
小数部分 0.13
有点棘手。 0.13
是 13/100
。我使用 Windows 计算器 (Programmer mode, hex) 并将 13
(hex D
) 向左移动 32(*) 位: D00000000
。将其除以 100
(十六进制 64
)得到:2147AE14
十六进制。
由于我们需要一个小于1的值,我们再次右移32位,得到:0.2147AE14
现在加上左边的整数部分:C.2147AE14
尾数只需要24位,所以四舍五入:C.2147B
--> C2147B
现在必须对其进行归一化,因此二进制小数点向左移动 3 位(当然,这些位保持不变)。指数(最初为 0)相应地增加了 3,所以现在是 3.
现在可以删除隐藏位:42147B
(现在是低 23 位)
现在可以将其转换为 32 位值:0x0042147B
指数和符号
现在我们来计算指数:3
+ 十六进制的偏差 7F
= 十六进制 82
,或 1000 0010
二进制。
在左边添加符号位:1 1000 0010
。重新分组:1100 0001 0
或 C10
当然这些是最高位,所以我们将其转换为 0xC1000000
以获得完整的 32 位
"Bitwise-Or" 两部分
0xC100000 | 0x0042147B = 0xC142147B
这就是您想要的值。
(*)32 位,所以我有足够多的位可以在稍后正确舍入。
要对浮点数进行编码,我们必须将其重写为(-1)s 2e 1.m
并将不同部分编码为 32 位如下
(来自 https://en.wikipedia.org/wiki/Single-precision_floating-point_format)
第一位是符号s:0代表+,1代表-
后面的8位是移位指数e+127
最后23位是尾数(m)的小数部分
困难的部分是将尾数转换为二进制。对于某些数字,这很容易。例如,5.75=4+1+1/2+1/4=22+20+2- 1+2-2=101.11=1.0111×22
对于其他数字(如您的数字),则更难。解决方案是将数字乘以二,直到找到整数或超过代码中的总位数 (23+1)。
我们可以为您的号码做到这一点:
12.13 = 12.13 2^-0
= 24.26 2^-1
= 48.52 2^-2
= 97.04 2^-3
= 194.08 2^-4
= 388.16 2^-5
= 776.32 2^-6
= 1552.64 2^-7
= 3105.28 2^-8
= 6210.56 2^-9
= 12421.12 2^-10
= 24842.24 2^-11
= 49684.48 2^-12
= 99368.96 2^-13
= 198737.92 2^-14
= 397475.84 2^-15
= 794951.69 2^-16
= 1589903.38 2^-17
= 3179806.75 2^-18
= 6359613.50 2^-19
= 12719227.00 2^-20
下一次迭代将导致大于 2^24(=~16M) 的数字,我们可以停止。
尾数代码很容易(但有点长)用通常的方法手工转换成二进制,它的代码是0xc2147b。如果我们把位置 223 的 1 处的前导位提取出来放在 "dot" 的左边,我们有 mantissa=1.42147b×223(其中小数部分限制为 23 位)。由于我们必须将初始数字乘以 220 才能得到这个值,所以我们最终得到
mant=1.42147b×23
所以指数是3,它的代码是3+127=130
exp=130d=0x82
并且因为数字是负数
sign=1
我们只需要抑制尾数(隐藏位)的整数部分并将这些数字连接起来以获得最终值 0xc142147b
(当然,我是用程序生成这些数字的,如果有兴趣,这里是C代码)
#include <stdio.h>
int main () {
float f=-12.13;
int sign=(f<0.0);
float fmantissa;
fmantissa = (f<0.0?-f:f) ; // abs value of f
int e = 0 ; // the raw exponent
printf("%2.2f = %11.2f 2^-%d\n",f,fmantissa,e);
while (fmantissa<=(1<<23)){
e++; fmantissa*=2.0;
printf(" = %11.2f 2^-%d\n",fmantissa,e);
}
// convert to int
int mantissa=fmantissa;
//and suppress hidden bit in mantissa
mantissa &= ~(1<<23) ;
// coded exponent
int exp=127-e+23;
printf("sign: %d exponent: %d mantissa: 1.%x\n",sign, exp, mantissa);
//final code
int fltcode = (sign << 31) | (exp << 23) | mantissa;
printf("0x%x\n",fltcode);
}
我学会了如何将数字转换为浮点数(在二进制、八进制和十六进制之上),并且知道如何将数字转换为浮点数。
但是,在查看给我的工作表时,我遇到了以下问题:
使用 32 位 IEEE 754 单精度浮点数以十六进制表示 -12.13。
我已经尝试查看我拥有的资源,但仍然无法弄清楚如何回答上述问题。给出的答案是0xc142147b.
编辑:抱歉没有澄清,但我想知道如何手动完成而不是编码。
-12.13
必须先转二进制再转十六进制。让我们或多或少像 glibc 库那样做,只使用笔和纸以及 Windows 计算器。
删除标志,但记住我们有一个:12.13
有效数(或尾数)
整数部分,12
很简单:C
(十六进制)
小数部分 0.13
有点棘手。 0.13
是 13/100
。我使用 Windows 计算器 (Programmer mode, hex) 并将 13
(hex D
) 向左移动 32(*) 位: D00000000
。将其除以 100
(十六进制 64
)得到:2147AE14
十六进制。
由于我们需要一个小于1的值,我们再次右移32位,得到:0.2147AE14
现在加上左边的整数部分:C.2147AE14
尾数只需要24位,所以四舍五入:C.2147B
--> C2147B
现在必须对其进行归一化,因此二进制小数点向左移动 3 位(当然,这些位保持不变)。指数(最初为 0)相应地增加了 3,所以现在是 3.
现在可以删除隐藏位:42147B
(现在是低 23 位)
现在可以将其转换为 32 位值:0x0042147B
指数和符号
现在我们来计算指数:3
+ 十六进制的偏差 7F
= 十六进制 82
,或 1000 0010
二进制。
在左边添加符号位:1 1000 0010
。重新分组:1100 0001 0
或 C10
当然这些是最高位,所以我们将其转换为 0xC1000000
以获得完整的 32 位
"Bitwise-Or" 两部分
0xC100000 | 0x0042147B = 0xC142147B
这就是您想要的值。
(*)32 位,所以我有足够多的位可以在稍后正确舍入。
要对浮点数进行编码,我们必须将其重写为(-1)s 2e 1.m 并将不同部分编码为 32 位如下
(来自 https://en.wikipedia.org/wiki/Single-precision_floating-point_format)
第一位是符号s:0代表+,1代表-
后面的8位是移位指数e+127
最后23位是尾数(m)的小数部分
困难的部分是将尾数转换为二进制。对于某些数字,这很容易。例如,5.75=4+1+1/2+1/4=22+20+2- 1+2-2=101.11=1.0111×22
对于其他数字(如您的数字),则更难。解决方案是将数字乘以二,直到找到整数或超过代码中的总位数 (23+1)。
我们可以为您的号码做到这一点:
12.13 = 12.13 2^-0
= 24.26 2^-1
= 48.52 2^-2
= 97.04 2^-3
= 194.08 2^-4
= 388.16 2^-5
= 776.32 2^-6
= 1552.64 2^-7
= 3105.28 2^-8
= 6210.56 2^-9
= 12421.12 2^-10
= 24842.24 2^-11
= 49684.48 2^-12
= 99368.96 2^-13
= 198737.92 2^-14
= 397475.84 2^-15
= 794951.69 2^-16
= 1589903.38 2^-17
= 3179806.75 2^-18
= 6359613.50 2^-19
= 12719227.00 2^-20
下一次迭代将导致大于 2^24(=~16M) 的数字,我们可以停止。
尾数代码很容易(但有点长)用通常的方法手工转换成二进制,它的代码是0xc2147b。如果我们把位置 223 的 1 处的前导位提取出来放在 "dot" 的左边,我们有 mantissa=1.42147b×223(其中小数部分限制为 23 位)。由于我们必须将初始数字乘以 220 才能得到这个值,所以我们最终得到
mant=1.42147b×23
所以指数是3,它的代码是3+127=130
exp=130d=0x82
并且因为数字是负数
sign=1
我们只需要抑制尾数(隐藏位)的整数部分并将这些数字连接起来以获得最终值 0xc142147b
(当然,我是用程序生成这些数字的,如果有兴趣,这里是C代码)
#include <stdio.h>
int main () {
float f=-12.13;
int sign=(f<0.0);
float fmantissa;
fmantissa = (f<0.0?-f:f) ; // abs value of f
int e = 0 ; // the raw exponent
printf("%2.2f = %11.2f 2^-%d\n",f,fmantissa,e);
while (fmantissa<=(1<<23)){
e++; fmantissa*=2.0;
printf(" = %11.2f 2^-%d\n",fmantissa,e);
}
// convert to int
int mantissa=fmantissa;
//and suppress hidden bit in mantissa
mantissa &= ~(1<<23) ;
// coded exponent
int exp=127-e+23;
printf("sign: %d exponent: %d mantissa: 1.%x\n",sign, exp, mantissa);
//final code
int fltcode = (sign << 31) | (exp << 23) | mantissa;
printf("0x%x\n",fltcode);
}