根据国际标准IEEE:任意一个二进制浮点数V可以表示为下面形式:
(-1)^SM2^E:
(-1)^S表示符号位,当S为0,V为正数;当S为1,V为负数。由其物理结构决定了,浮点数为有符号数。
M为有效数字,大于等于1,小于2。
2^E表示指数位。
eg:5=>0101=>(-1)^01.012^2. S=0,M=1.01,E=2
规定:对于32位的浮点数(单精度浮点数存储),最高1位是符号位(S),接着的8位为指数位(E),剩下的23位是有效数字位(M),不满23位后面补0。
对于64位的浮点数(双精度浮点数存储),最高1位是符号位(S),接着的11位为指数位(E),剩下的52位是有效数字位(M)。
对于有效数字M和指数E会有一些特殊规定:
1、因为1<=M<2,所以小数点前必定是1,所以可以省略1和小数点,这样一来,对于单精度浮点数存储方式,23位有效数位存的都是小数部份数。读取时,小数点和1都会被自动加上。等于可以保留24位有效数字。双精度同理。
2、对于指数E来说,首先说明他是一个无符号整数,对于单精度浮点数存储方式,E共占8位,则E的取值范围为0~255。但是科学记数法中,指数是可以为负数的,所以规定,存入内存时,E的真实值必须加上一个中间数,对于8位的E,这个中间数为(255/2=)127(实际表达范围-127~128),对于11位的E,这个中间数为1023(实际表达范围-1023~1024)。取数时,再减去127/1023即为实际值。(移码)
eg. 由上面可知,5的指数为2,对于单精度浮点数存储方式,实际在内存中存储的数为127+2=129=>1000 0001。
注意:因为当E为全零时,实际上指数为-127,表示一个接近零很小的数,因此浮点数不能与零比较,用精度来代替。当E为全一时,表示的±无穷大。
综述:整数与浮点数的存储方式完全不同,整数存取为原反补码,浮点数为S、E、M
练习代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
int main()
{
int n = 9; //0000 0000 0000 0000 0000 0000 0000 1001
float pFloat = (float)n; //将9取出,转为浮点型,再存给pFloat
float *pfloat = (float *)&n; //将n的地址转为浮点数地址(即看待n的方式变为浮点数)。
printf("n=%d\n", n);
printf("pFloat=%f\n", pFloat);
printf("*float=%f\n", *pfloat); //解引用后以浮点数形式看待空间里的值 0 00000000 00000000000000000001001 S=0,E=0,(-127)
*pfloat = 9.0; //1001 实际n空间中存的值0 00000011 00100000000000000001001
printf("n=%d\n", n); //转换为整数为 1091567616
printf("*float=%f\n", *pfloat); // 9.000000
system("pause");
return 0;
}
原文地址:https://blog.51cto.com/14240895/2385761