简要记录浮点型数据的二进制存储格式

来源:互联网 发布:ubuntu wifi 连不上 编辑:程序博客网 时间:2024/05/21 20:56

转自:http://blog.csdn.net/joyzml/archive/2011/02/25/6206913.aspx

http://bbs.pediy.com/showthread.php?t=55241


浮点数包括float和double两种类型,float占32位,double占64位。其二进制存储格式遵循IEEE754标准。以float为例:

      

      符号位:正数为0,负数为1

      以float型数据123.456为例,分析其二进制存储格式:

      首先将十进制数123.456转换为二进制数为:1111011. 01110100101111001 

      (其中0.456如何转换为二进制?不断乘以2…)

      1111011. 01110100101111001 即1. 11101101110100101111001乘以2的6次方

      首先这是一个正数,则符号位为0

      阶码为6,不过要转换成移码。

      (如何求6的移码?这里我也不太深究,我见大家都是直接6+127=133,换为2进制为10000101)

      (移码与补码的关系: [X]移与[X]补的关系是符号位互为相反数(仅符号位不同))

      尾数则为1. 11101101110100101111001的小数部分,即

11101101110100101111001

综上:123.456的二进制存储格式为:01000010111101101110100101111001

用一段代码来验证一下:

#include <cstdlib>

#include <iostream>

using namespace std;

void printBinary(const unsigned char val)

{

      for(int i = 7; i >= 0; i--)

           if(val & (1 << i))

                 std::cout << "1";

           else

                 std::cout << "0";

}

int main()

{

      float d = 123.456;

      unsigned char* cp = reinterpret_cast<unsigned char*>(&d);

      for(int i = sizeof(float)-1; i >= 0 ; --i)

      {

           printBinary(cp[i]);

      }

      system("PAUSE");

}

      要注意的是,X86架构为小端模式,是指数据的低位保存在内存的低地址中,而数 据的高位保存在内存的高地址中。所以上面的for(int i = sizeof(float)-1; i >= 0 ; --i)先打印高地址部分,即二进制的高字节数据。

      程序的执行结果:

      

01000010111101101110100101111001

      对比一下刚才的分析结果是相同的。

      double类型和float类型的二进制存储格式是同样的道理。

 

我们知道任何一个数都可以按科学计数法表示成A×10的B次方的形式,其中1.0≤A<10,B为整数。同样的道理,也可以表示成C×010的D次方的形式,其中010表示2的二进制表示,C为二进制浮点数,D为二进制整数。例如5.0用二进制表示就是0101,也就是可以表示成(1.01)×010的2次方的形式。知道了这点,我们来看一下在VC里面是怎样来存储double型数据的。
在VC里面,double型数据占据了8个字节,共64位。
最高位是符号位,0表示正,1表示负。
接下来的11位表示指数,用移码表示,关系为:11位数组成的值(无符号)-1023=指数,如上所示5.0的指数部分是2,11位数组成的值应该是1025,即100 0000 0001
余下的52位是小数位,其中1.0……中的1是默认的,没有占据位数。5.0的小数部位是1.01,则它的小数位在内存中应该表示成0100 0000 0000 ……0000(共52位)
所以+5.0在内存中存储的形式应该是0100 0000 0001 0100 0000 …… 0000即0x40140000 00000000。
下面我们通过一个程序来验证一下:
#include "stdafx.h"
#include "iostream.h"

typedef union tagOct
{
  double dData;
  int nData[2];
}Oct;

int main(int argc, char* argv[])
{
  Oct a;
  a.nData[0]=0;
  a.nData[1]=0x40140000;
  cout<<a.dData<<endl;
  return 0;
}
相信这段代码很好理解,先通过整形数组给共用体赋值,再以浮点的形式输出,最后的结果果然是5。如果把0x40140000改成0xC0140000呢,相信你很快就得到答案,是-5,不相信?去试试吧。
附:float型和double型基本一样,只是它用8位表示指数,用23位表示小数,另外它的移码表示不是相差1023(2的10次方-1),而是127(2的7次方-1)。有兴趣可以试验一下。

0 0
原创粉丝点击