本帖最后由 yongheng0852 于 2017-10-12 23:39 编辑
目标:
学习:IEEE754浮点数存储的相关知识
验证:浮点数在计算机中的存储方式:近似存储
一:数据存储方式
二: IEEE 754 关于浮点数的规定
三:十进制数转换成浮点数的步骤
四:数据转换案例
五:几个特殊数据的存储规则
六:浮点数转换成十进制数的步骤
七:实际应用
一:数据存储方式:
1.整型:以补码的方式存储
正整数:源码,反码,补码 都相等。
负整数:补码为(符号位不变),源码的反码加1
2.浮点数:以IEEE754标准存储。
二: IEEE 754 关于浮点数的规定
在计算机中,浮点数一般由三部分组成:
数值的符号位、阶码和尾数。
这种浮点数是用科学记数法来表示的,即:
浮点数=符号位.尾数×2阶码。
1.据IEEE 754国际标准,常用的浮点数有两种格式:
(1)单精度浮点数(32位),阶码8位,尾数24位(内含1位符号位)。
(2)双精度浮点数(64位),阶码11位,尾数53位(内含1位符号位)。
(3)临时浮点数(80位),阶码15位,尾数65位(内含1位符号位)。
2.根据IEEE 754标准:
(1)符号位也是“0”代表正数;“1”代表负数.
(2)阶码用移码表示,尾数规格化形式,但格式如下:
1.XXX…X。
由于最高位总是1,因此省略,称隐藏位(临时实数则不隐藏).
尾数比规格化表示大一倍,而阶码部分则比一般小1,
即[E]移=2n+E-1=127+E
这样,尾数与通常意义的尾数的含义不一致,为了区别,754 中的尾数称为有效数.
3.IEEE754对阶码作如下规定偏移阶码E实际阶码值
0保留做操作数
1-126
2-125
…
1270
1281
1292
…
254127
255保留做操作数
4.对上溢和下溢的处理
当运算结果小于规格化浮点数所能表示的最小值时,以前硬件处理策略,或者结果置0或者产生一个下溢陷阱,这两种方案均不能令人满意。
IEEE754处理方法是使用非规格化数。这时阶码为0(即移码-127),尾数没有隐含位,最高位是0。
这样的结果是降低精度,扩大表示范围。如原来规格化单精度最小值是1.0x2-126,而非规格化单精度最小值是2-23 x2-126=2-149(只有1位有效位)。
5. 对上溢用无穷大表示,同时规定:
无穷大+任何数=无穷大
任何有限数÷0=无穷大
任何有限数÷无穷大=0
无穷大÷无穷大=NaN
NaN(Not A Number)
6.这样IEEE754有5种类型浮点数据,如下表:SEM意义
0/100±0
0/10非0非规格化数
0/11~254任意规格化数
0/12550±无穷大
0/1255非0NaN
三:十进制数转换成浮点数的步骤
1.将十进制数转换成二进制数:
(1)整数部分用2来除,小数部分用2来乘;
a)整数部分转二进制((按源码的二进制形式)
b)小数部分转换
2.规格化二进制数:
(1)科学计数法方式表示,使小数点前面仅有第一位有效数字,改变阶码(阶码由10进制转换为2进制)
3.计算阶码
(1)短型浮点数的阶码加上偏移量7FH
(2)长型浮点数的阶码加上偏移量3FFH
(3)扩展型浮点数的阶码加上偏移量3FFFH
4.尾码计算
(1)尾码是小数点后的数据
(2)如果尾码不足23位,则后面补零
(3)大于23位只保留23bit,如果后一位为1时,向前进1。
5.以32bit浮点数据格式存储。
(1)把数值的符号位、阶码和尾数合在一起就得到了该数的浮点存储形式。
四:数据转换案例
例1-把十进制数100.25转换成协处理器中的浮点数
解:
(1)进制转换:
(100.25)10=(1100100.01)2
(2)规格化:
(1100100.01)2=1.10010001×26 =1.10010001×2110
(3)计算阶码(阶码+偏移量(7FH))
110+01111111=10000101
(4)尾码计算(不足23位)
10010001 0000 0000 0000 000
(5)组合
符号位(01bit) 0,
阶码为(08bit) 10000101,
尾数为(23bit) 10010001000000000000000
组合后的32bit数据: 01000010110010001000000000000000
16进制: 0x42C88000
综合上述可得:
(100.25)10的浮点形式为:0x42C88000
1.程序验证(VS2015-控制台程序)
[C] 纯文本查看 复制代码#define _CRT_SECURE_NO_WARNINGS
#include
#include
int main(void)
{
float a = 100.25f;
unsigned int* p = (unsigned int*)&a;//以无符号的方式操作,避免了转码问题,(浮点数,转换为正整数)
int len = sizeof(float);
int i;
char k;
printf("p = %p\n", p);//打印变量地址
printf("len = %d\n", len);//打印变量的长度
printf("a = %f\n", a);//输出原始数据
printf("----------------------------------\n");
for (i = 31; i >= 0; --i)//实际存入的数据是
{
k = (*p) >> i & 1;//右移,从高位开始提取,与运算,按位提取
printf("%d ", k);
if (31 == i || 23 == i)//输出分隔符
printf(" - ");
}
printf("\n");
system("pause");
return 0;
}
(100.25)10的浮点形式:0x42C88000
1.png (4.89 KB, 下载次数: 4)
2017-10-12 00:26 上传
2.png (18.81 KB, 下载次数: 0)
2017-10-12 00:27 上传
小端对齐:
数值的高位字节存储在内存的低位地址上,数值的低位字节存储在内存的高位地址上。
例2 -把十进制数-33.33转换成协处理器中的浮点数
解:
(1)进制转换:
(33.33)10=(100001. 01010100011110101110000)2
(2)规格化:
(100001.01010100011110101110000)2
=1.0000101010100011110101110000)2×25
=1.0000101010100011110101110000)2×2101
(3)计算阶码(阶码+偏移量(7FH))
101+01111111=10000100
(4)尾码计算(超过23位,后位为1,则进1)
0000 1010 1010 0011 1101 011 10000
0000 1010 1010 0011 1101 100
(5)组合
符号位(01bit) 1,
阶码为(08bit) 10000100,
尾数为(23bit) 0000 1010 1010 0011 1101 100
组合后的32bit数据: 110000100000010101010 00111101100
16进制: 0xC20551EC
综合上述可得:
(-33.33)10的浮点形式为:0xC20551EC 再次解读数据: -33.330002
再把: 0xC20551EC 还原为10进制,则数据为:-33.330002
浮点数在计算机中采用近似的方式存储。
为什么后面会多了0.000002,这是因为我们在计算尾码的时候,尾码超过了23位,舍去了23位后面的数据,第24bit为1,向前进1, 所以多了0.000002
2.程序验证 (VS2015-控制台程序)
[C] 纯文本查看 复制代码#define _CRT_SECURE_NO_WARNINGS
#include
#include
int main(void)
{
float a = 100.25f;//-33.33f是个很有代表型的数字,它再一次证明了浮点数是不能精确存储的
unsigned int* p = (unsigned int*)&a;
int len = sizeof(float);
int i;
char k;
printf("p = %p\n", p);
printf("len = %d\n", len);
printf("a = %f\n", a);//输出原始数据、但实际输出的是-33.330002
printf("----------------------------------\n");
for (i = 31; i >= 0; --i)
{
k = (*p) >> i & 1;//与运算,按位提取
printf("%d ", k);
if (31 == i || 23 == i)
printf(" - ");
}
printf("\n");
system("pause");
return 0;
}
(-33.33)10的浮点形式为: 0xC20551EC 再次解读数据: -33.330002
3.png (17.36 KB, 下载次数: 0)
2017-10-12 00:29 上传
4.png (22.5 KB, 下载次数: 0)
2017-10-12 00:29 上传
具体推导过程:(无法上传excel,只能传图片了)
AA.png (134.75 KB, 下载次数: 1)
2017-10-12 00:51 上传
BB.png (370.59 KB, 下载次数: 0)
2017-10-12 00:51 上传
五:几个特殊数据的存储规则:
1.正0: 所有的数据位都是0;
2.负0: 最高位为1,其它的数据位是0;
3.正/负无穷: 符号位为0/1,阶码位全为1,有效数字全为0;
NAN: 非法的浮点数,阶码位全为1,有效数字不全为0;
其中:NAN —Not-A-Number。
六:浮点数转换成十进制数的步骤
1.该步骤与前面“十进制数转换成浮点数”的步骤是互逆的,其具体步骤如下:
(1)分割数字的符号、阶码和有效数字;
(2)将偏移阶码减去偏移,得到真正的阶码;
(3)把数字写成规格化的二进制数形式;
(4)把规格化的二进制数改变成非规格化的二进制数;
(5)把非规格化的二进制数转换成十进制数。
例3 -把浮点数
1100000111001001000000000000转换成十进制数。
解:
1.把浮点数 1100000111001001000000000000
分割成三部分,可得:
(1)符号位是1,
(2)阶码 是10000011,
(3)尾数 是1001001000000000000
2.还原阶码:
10000011 –01111111=100
3.该浮点数的规格化形式:
1.1001001×24
(其中前面的“1.”从隐含位而来)
4.该浮点数的非规格化形式:
11001.001
5.该浮点数的十进制数为-25.125 (因为符号位为1,所以,该数是负数)
七:实际应用(工业):
设备说明:采集测试产品在指定温度的阻抗状态
在温度检测项目中,测试仪器使用的是8位CPU(8bit单片机)把采集的实际温度和电阻值数据以IEEE754的格式,通过modbus协议,按8bit的方式发送,连续发送4次,接收设备接收到数据之后,必须按照IEEE754格式再转换为浮点数才能使用,上位机把数据转换完成在对外部做相应的逻辑控制。
A.png (172.75 KB, 下载次数: 0)
2017-10-12 00:32 上传测控仪器发送----à---à---à---à----上位机接收后转换
数据142C7合并数据:42C785E9
85E9转换浮点:99.76154327
数据2419D合并数据:419DCA4C
CA4C转换浮点:19.72377777
数据3C7C3合并数据:C7C35000
500转换浮点:-100000
数据4C7C3合并数据:C7C35000
500转换浮点:-100000
数据5C7C3合并数据:C7C35000
500转换浮点:-100000
数据6C7C3合并数据:C7C35000
500转换浮点:-100000
合计24个字节/4 = 6组数据
参考资料:
1.单精度浮点数的存储-郝斌老师
2.IEEE-754关于浮点数的规定.ppt 百度文库
因初学C,以上是个人在网上搜集了一些资料,学习完后个人的理解,下面也只是小弟的一些不成熟的心得,不对之处恳请指正!
我的Email是 yongheng0852@live.cn,不对之处,恳请诸位诸位发邮件指正!
2017年10月11日 深圳黑马6期