32位IEEE 754单精度浮点数到十六进制

时间:2019-03-01 15:39:00

标签: floating-point hex ieee-754

我已经学习了如何将数字转换为浮点数(在二进制,八进制和十六进制之上),并且知道如何将数字转换为浮点数。

但是,在浏览工作表时,遇到了以下问题:

使用32位IEEE 754单精度浮点以十六进制表示-12.13。

我尝试查看自己拥有的资源,但仍然不知道如何回答上述问题。给出的答案是 0xc142147b

编辑:对不起,您不清楚,但我想知道如何手动完成此工作,而不是对其进行编码。

2 个答案:

答案 0 :(得分:0)

-12.13必须先转换为二进制,然后再转换为十六进制。让我们或多或少像 glibc 库那样做,只使用笔和纸以及Windows计算器。

删除标志,但请记住我们有一个标志:12.13

有效数(或尾数)

整数部分12很简单:C(十六进制)

小数部分0.13有点棘手。 0.1313/100。我使用Windows计算器(程序员模式,十六进制),并将13(十六进制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 0C10

当然,这些是最高位,所以我们将完整的32位变成0xC1000000

“按位或”两个部分

0xC100000 | 0x0042147B = 0xC142147B

这就是您想要的值。


(*) 32位,所以以后有足够的位数可以正确取整。

答案 1 :(得分:0)

要编码一个浮点数,我们必须将其重写为(-1) s 2 e 1.m 并将不同部分编码为32位,如下所示

enter image description here

(来自https://en.wikipedia.org/wiki/Single-precision_floating-point_format

  • 第一位是符号s:+表示0,--

  • 以下8位是移位的指数e + 127

  • 最后23位是尾数(m)的小数部分

困难的部分是将尾数转换为二进制。对于某些数字,这很容易。例如,5.75 = 4 + 1 + 1/2 + 1/4 = 2 2 +2 0 +2 -1 +2 < sup> -2 = 101.11 = 1.0111×2 2

对于其他数字(如您的数字),则难度更大。解决方案是将数字乘以2,直到找到整数或超过代码中的总位数(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)的数字,我们可以停止。

Mantissa代码很容易(但有点长),可以使用通常的方法手动转换为二进制,其代码为0xc2147b。如果我们提取位置2 23 中1处的前导位并将其放在“点”的左侧,则尾数= 1.42147b×2 23 (其中小数部分是限制为23位)。由于我们必须将初始数字乘以2 20 才能获得此值,所以我们最终有了

  

mant = 1.42147b×2 3

所以指数是3,代码是3 + 127 = 130

  

exp = 130 d = 0x82

并且数字为负

  

符号= 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);
}