浮点型在内存中的存在方式

介绍

c=[100.0,-100.0,-0.5,10.25]  ;idl代码,表示float型的array
allen@xps:~$ od -x sample
0000000 0000 42c8 0000 c2c8 0000 bf00 0000 4124
0000020

也就是说float数组在内存中是这个样子

0000 42c8 0000 c2c8 0000 bf00 0000 4124

100 ->0000 42c8
-100->0000 c2c8
注意我们应该把上面的16进制数倒过来看,也就是
42c8 0000=0100 0010 1100 1000 0000 0000 0000 0000=0 10000101 10010000000000000000000=+(1.1001)2×2128+4+1127=(1100100)2=100
c2c8 0000=1100 0010 1100 1000 0000 0000 0000 0000=1 10000101 10010000000000000000000=(1.1001)2×2128+4+1127=(1100100)2=100
可见只有符号位改变了
所以,原码/反码/补码的概念只适用于整形!

但是上面怎么倒过来了,,内存中本来就是这样的吗?

还有,用hexedit打开的话,是这个样子:

00 00 C8 42 00 00 C8 C2 00 00 00 BF 00 00 24 41

什么鬼?

再试了一下用Sublime TextEdit 3打开,也是和hexedit打开一样(这应该是内存中真正的样子)

0000 c842 0000 c8c2 0000 00bf 0000 2441

但如果按照
IEEE 754
这种读法的话,应该这样看

42c8 0000 c2c8 0000 bf00 0000 4124 0000

当一个文件中包含了int型

#include <stdio.h>
int main()
{
    unsigned int a[]={0,1,2,3};
    int b[]={0,1,2,3};
    int c[]={0,-1,-2,-3};
    int d[]={131072,262144,524288,524288*2};  //2^17, 2^18 and so on
    FILE *file;
    file=fopen("/home/allen/sample_int","w");
    fwrite(a,sizeof(unsigned int),4,file);
    fwrite(b,sizeof(int),4,file);
    fwrite(c,sizeof(int),4,file);
    fwrite(d,sizeof(int),4,file);
    fclose(file);
    return 0;
}

subl 打开

0000 0000 0100 0000 0200 0000 0300 0000
0000 0000 0100 0000 0200 0000 0300 0000
0000 0000 ffff ffff feff ffff fdff ffff
0000 0200 0000 0400 0000 0800 0000 1000

仍然,按照我们认知的习惯,需要这样读,例如-2
IEEE 754标准下是11111111 11111111 11111111 11111110ffff fffe
倒转2次得到feff ffff
再如2^17=131072
IEEE 754标准下是00000000 00000010 00000000 000000000002 0000
倒转2次得到0000 0200

abcd efghab¯¯¯¯|cd¯¯¯¯¯¯¯¯cd¯¯¯¯|efefcd cdab

或许用数字表示更清楚:
1234 567812¯¯¯¯|34¯¯¯¯¯¯¯¯56¯¯¯¯|787856 3412

事实上上面的表示方法是十六进制的表示方法,也就是说上面的12345678实际上是{12}{34}{56}{78}四个字节,我们用ABCD来表示, 则上面的反转公式就可以简单地表示为:
ABCDDCBA

看到这里应该明白了,其实内存中储存的就是课本上所教的补码(整形)和IEEE 756定义的浮点型,为什么反过来储存呢,这是系统决定的,即采用Little EndianBig Endian(这个没求证过,我以前只知道Little/Big Endian会决定一个字节bit之间顺序上的储存方式,现在看来好像也会决定字节之间顺序上的储存关系)

同时要注意到单个byte在显示的时候并没有翻转过来,也就是可以两个数字``两个数字地读

这样说来,一开始使用的 od -x 命令其实是帮住用户把连续的两个字节倒过来,但感觉这没必要啊,并不是所有的类型都是两个字节表示的(如果真是这样确实是方便了)。难道是为了方便用户四个数字``四个数字地读?

再来拿double练习一下:

上面的C代码中在合适的位置加入

double e[]={1.0,3.0,100,-100};


fwrite(e,sizeof(double),4,file);

输出的文件中增加了这样两行

0000 0000 0000 f03f 0000 0000 0000 0840
0000 0000 0000 5940 0000 0000 0000 59c0

有了前面的结论直接阅读之:

  • 取前面8个字节,并反转之得到 3ff0 0000 0000 0000
  • 变成二进制 0011 1111 1111 {0000}x13
  • 变成IEEE 754double格式0 01111111111 {0}x52
  • 变成十进制数字+1.0×221011023=1 , 完成,正确

  • 取最后8个字节,c059 0000 0000 0000

  • 1100 0000 0101 1001 {0000}x12
  • 1 10000000101 1001{0}x48
  • 1.1001×220+22+2101023=(1100100)2=(4+32+64)=100 ,完成,正确

延伸阅读
Big and Little Endian

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章