十进制浮点数的二进制转换及存储

来源:互联网 发布:plc编程自制功能块 编辑:程序博客网 时间:2024/06/05 14:37

网上看到一道小题:

int main(void) 
{
float a = 10.0;

double b = 10.0;

printf( "%d\n", a );

printf( "%d\n", b );

return 0;

}

输出结果a,b均为0。

这道小题是一个很好的面试题,考查面试者对浮点数存储的理解。


十进制小数的二进制表示:

整数部分:除以2,取出余数,商继续除以2,直到得到0为止,将取出的余数逆序

小数部分:乘以2,然后取出整数部分,将剩下的小数部分继续乘以2,然后再取整数部分,一直取到小数部分为零为止。如果永远不为零,则按要求保留足够位数的小数,最后一位做0舍1入。将取出的整数顺序排列。

举例:22.8125 转二进制的计算过程:

整数部分:除以2,商继续除以2,得到0为止,将余数逆序排列。
22 / 2  11 余0
11/2     5  余 1
5  /2      2  余 1
2  /2      1  余 0
1  /2      0  余 1
得到22的二进制是10110


小数部分:乘以2,取整,小数部分继续乘以2,取整,得到小数部分0为止,将整数顺序排列。
0.8125x2=1.625 取整1,小数部分是0.625
0.625x2=1.25 取整1,小数部分是0.25
0.25x2=0.5 取整0,小数部分是0.5
0.5x2=1.0 取整1,小数部分是0,

得到0.8125的二进制是0.1101

结果:十进制22.8125等于二进制00010110.1101


浮点数的计算机存储:

IEEE 754标准中所定义的单精度32位浮点数和双精度64位浮点数的格式:

32位单精度

单精度二进制小数,使用32位存储。
1 8 23 位长
+-+--------+-----------------------+
|S| Exp | Fraction |
+-+--------+-----------------------+
31 30 23 22 0 位编号 (从右边开始为0)
偏正值 +127

64位双精度

双精度二进制小数,使用64位存储。
1 11 52 位长
+-+--------+-----------------------+
|S| Exp | Fraction |
+-+--------+-----------------------+
63 62 52 51 0 位编号 (从右边开始为0)
偏正值 +1023


单精度的E为指数值+127,双精度的E为指数值+1023,IEEE标准要求浮点数必须是规范的,也就是说尾数的小数点左侧必须为1,因此在保存尾数时可以省略小数点左侧的1,这样实际上对于float类型我们是用了23bits表示了24bits尾数。


以32位单精度浮点数为例:

十进制22.8125转换为二进制表示为00010110.1101,

00010110.1101 = 1.01101101 * 2^4

由此得出 符号位S为0,表示正数

指数位E为4+127=131D=10000011B

尾数F为1.01101101去掉小数点左侧的1,即为01101101


这样十进制22.8125转换为二进制表示为00010110.1101,计算机存储为01000001101101101000000000000000


0 1000001101101101000000000000000

1bit 8bits 23bits
 S
 E  F
符号位
指数位尾数位


回头再看最开始的小题,就容易多了。

10.0的二进制表示为1010.0= 1.010*2^3


float类型的10.0:

符号位S为0

指数E为3+127=130=10000010

尾数F为010


double类型的10.0:

符号位S为0

指数E为3+1023=1026=10000000010

尾数F为010


最终结果:

float类型的10.0转换为二进制为1010.0存储形式为01000001001000000000000000000000,16进制表示为0x41200000

double类型的10.0转换为二进制为1010.0存储形式为0100000000100100后面用0补全,16进制表示为0x40240000


代码验证一下:

int main(void) 
{
    float a = 10.0;
    double b = 10.0;
    int * pa = (int *)&a;
    int * pb = (int *)&b;


    printf( "%d\n", a );
    printf( "%x\n", *pa );
    printf( "%x\n", *(pb+1) );
    
return 0;
}

输出结果:

$ ./a.out
0
41200000
40240000


IEEE 754 单精度浮点数转换,在线计算http://www.styb.cn/cms/ieee_754.php

0 0
原创粉丝点击