计算机中浮点数是以IEEE754的新格式存放
一个32位的浮点数,其最高位是符号位,然后有8位是阶码,最后有23位尾数
符号位不必说,0表示正,1表示负
浮点数的存放,先将浮点数转为1.n*2^m这种形式,其中m为阶码数,n为尾数
下面我们看一下3.1416的存储
最高位符号位为
0
3.141600=1.5708*2^1
阶码数是1,尾数是0.5708
阶码数转为阶码是1+127=128 二进制为
1000 0000
尾数0.5708转成23位尾数是
100 1001 0000 1111 1111 1001
尾数转二进制的方法很简单,不断的乘2,,每乘一次2 ,就写一位,乘的结果没超过1就写0,超过1,就写1并减去1,一直乘到够自己用,或者没有小数为止
这里我们就得到了3.1416存储的这32位数
0100 0000 0100 1001 0000 1111 1111 1001
十进制就是 1078530041 ,十六进制就是0X40490FF9
那么,问题来了。那个776530087是怎么来的?它是个什么鬼?
这个问题是C语言的存储与printf输出之间的差异造成的。
printf格式化输出,%f既可以输出单精度(32位)也可以输出双精度(64位),所以不管是单精度还是双精度,在输出之前都会被转成双进度。
3.141600转成双进度存储格式为0
1000000 00001001 00100001 11111111 00101110 01001000 11101000 10100111。 1位符号位,11位阶码,52位尾数(可以看一下,这个52位尾数的前23位和上面的那个23为尾数是一样的的)
然后以%d输出实际上输出的是它的前32位,注意,所谓的前32位不是上面这一串的前32位,
计算机中小端存储,低位在前,高位在后,所以输出的实际上是那64位的后半部分。
可以用union看一下他们的存储。
- #include <stdio.h>
- union Data{
- float a;
- short b[2];
- char c[4];
- int d;
- };
- union Num{
- double lf;
- int d[2];
- char ch[8];
- };
- int main()
- {
- union Data aaa;
- aaa.a=3.141600;
- int i=0;
- printf("float类型的3.141600存储,占4个字节\n");
- printf("a=%f\n两个双字节以16进制显示:",aaa.a);
- for(i=0;i<2;i++)
- printf("b[%d]=%x ",i,aaa.b[i]);
- printf("\n两个双字节以10进制显示:");
- for(i=0;i<2;i++)
- printf("b[%d]=%d\t",i,aaa.b[i]);
- printf("\n四个单字节:");
- for(i=0;i<4;i++)
- printf("c[%d]=%d\t",i,aaa.c[i]);
- printf("\n一个四字节以16进制显示:d=%x\n",aaa.d);
- union Num num;
- num.lf=3.141600;
- printf("\ndouble类型的3.141600存储,占8个字节\n");
- printf("f=%f\n两个四字节以16进制显示:",num.lf);
- for(i=0;i<2;i++)
- printf("d[%d]=%x\t",i,num.d[i]);
- printf("\n两个四字节以10进制显示:");
- for(i=0;i<2;i++)
- printf("d[%d]=%d\t",i,num.d[i]);
- printf("\n八个单字节:");
- for(i=0;i<8;i++)
- printf("ch[%d]=%d\t",i,num.ch[i]);
- return 0;
- }
复制代码
结果:
- float类型的3.141600存储,占4个字节
- a=3.141600
- 两个双字节以16进制显示:b[0]=ff9 b[1]=4049
- 两个双字节以10进制显示:b[0]=4089 b[1]=16457
- 四个单字节:c[0]=-7 c[1]=15 c[2]=73 c[3]=64
- 一个四字节以16进制显示:d=40490ff9
- double类型的3.141600存储,占8个字节
- f=3.141600
- 两个四字节以16进制显示:d[0]=2e48e8a7 d[1]=400921ff
- 两个四字节以10进制显示:d[0]=776530087 d[1]=1074340351
- 八个单字节:ch[0]=-89 ch[1]=-24 ch[2]=72 ch[3]=46 ch[4]=-1 ch[5]=33 ch[6]=9 ch[7]=64
复制代码