2.IEEE 64位浮点数格式
这种格式的特点是:每个数由8字节组成,包括1位符号位,11位带符号阶码,52位尾数。
例如:我们收到一个数的格式是 3F F0 6F 80 00 00 00 00,那么它的二进制格式是:
0011 1111 1111 0000 0110 1111 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000
这时我们就可以得到这些信息:
符号位:0 (1表明这个数是个负数,0表明这个数是正数)
带符号的阶码:011 1111 1111 (转化为整数是1023)
尾数:0000 0110 1111 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000
首先计算指数:
指数:阶码 - 1023 = 0;表明此尾数不需要移位
然后对尾数进行处理:在尾数的最高位加上一个隐藏位1,形成如下二进制格式:
1 0000 0110 1111 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000
其中小数点的位置就在刚加的隐藏位后,即:
1.0000 0110 1111 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000
次数不用移位,故得到最终的浮点数二进制格式为:
1.0000 0110 1111 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000
计算此二进制格式为
1*(2^-0) + 0*(2^-1) + 1*(2^-2)+ 0*(2^-2) + 1*(2^-3) + 1*(2^-4) + 0*(2^-5) + 1*(2^-6) + 1*(2^-7) + 0*(2^-8) + 1*(2^-9) + 1*(2^-10) +1*(2^-11) + 1*(2^-12) + 1*(2^-13) + 0*(2^-14)+ …. + 0*(2^-52)
计算后的十进制数1.02722168,根据前面的符号位可知,这是个正数,所以最终结果是1.02722168
C语言实现代码
long long int getS(int e,int m)
{
long long int s=e;
for (int i=1;i<m;i++)
{
s*=e;
}
return s;
}
double hex2double(unsigned char*p,double& result)
{
long long int a=0x0000000000000000;
a=a|p[0];
a=(a<<8)|p[1];
a=(a<<8)|p[2];
a=(a<<8)|p[3];
a=(a<<8)|p[4];
a=(a<<8)|p[5];
a=(a<<8)|p[6];
a=(a<<8)|p[7];
int s=(a>>63)&0xFF;//获得符号位,1表示负数,0表示正数
int e=(a>>52)&0x7FF;
e=e-1023;//获得指数
long long int m=a&0xFFFFFFFFFFFFF|0x10000000000000;//获得底数
//cout<<setiosflags(ios::uppercase)<<hex<<m<<endl;
long long int c=0;
double v=0.0,y=1.0;
if (e>=0)//向右移动
{
c=(m>>(52-e))&0xFFFFFFFFFFFFFFFF;//获得整数的二进制
long long int b=0;
for (int i=0;i<52-e;i++)
{
b=(b<<1)|0x01;
}
b=b&m;//获得小数的二进制
int j=0;
for (int i=52-e-1;i>=0;i--)
{
j++;
y=(double)(((b>>i)&0x01)*getS(2,j));
if (y>0.0)
{
v+=1.0/y;
}
}
v=c+v;
if (s>0)
{
v=-v;
}
}
else//向左移动
{
e=-e;
c=m;
int j=0;
for (int i=52+e-1;i>=0;i--)
{
j++;
y=(float)(((c>>i)&0x01)*getS(2,j));
if (y>0.0)
{
v+=1.0/y;
}
}
if (s>0)
{
v=-v;
}
}
result = v;
return v;
}
注:做个笔记,以备不时之需。