引子:
阅读一段代码:
int n = 9; //以整数的形式存储
float* pFloat = (float*)&n;
printf("%d\n", n); //输出 9
printf("%f", *pFloat); //输出 0.000000 这里以 浮点形式读取
*pFloat = 9.0; //以浮点的形式存储
printf("%d\n", n); //输出 1091567616 //以整数的方式读取
printf("%f\n", *pFloat); //输出 9.000000 00
这里会发现,
浮点数在内存中的存储读取
和
整数在内存中的读取存储
是存在差异的,并不是单纯的以二进制序列的形式存储在内存中。
浮点数存储规则:
根据国际标准IEEE(电气和电子工程)754,任意一个二进制浮点数V,可以表示成以下的形式
(-1)^S * M * 2^E
(-1)^S 表示符号位,S=0时,V为正数,S=1时,V为负数
M表示有效数字,大于等于1,小于2
2^E表示指数位。
一、浮点数的存储
浮点数:5.5 二进制序列:101.1
科学计数法:1.011*2^2
1.011 * 2^2 这里为正数,(-1)^0 的
0就是S
,1.011 的
011就是有效数字M
,2^2 的
幂数2就是指数E
。
float为4个字节,4个字节分位32个比特位,
最左边位存的是符号位
,第
31到24位存的是指数位
,
剩下的23个比特位存的是有效数字M
。
S就表示浮点数的符号位,(-1)^S,这里会发现
S=0,就为正数(1),S=1就为负数(-1)
。(整形类型1为负数,0为正数)。
-
PS:二进制数用科学计数法表示的浮点数,小数点前面一定是1,所以可以省略不存,M只存小数点后面的数。
IEEE754规定,
指数E为无符号整数(0~255)
,但是在科学计数法中,指数是存在负数的。所以这里又规定了,指数E实际上在内存中的存储,不管本身是负数还是正数,都要
加上一个127(double类型是1023)。
这里指数是 2 加上 127 等于 129。二进制序列:1000 0001
5.5在内存中存储的二进制位就是:0 1000 0001 01100000000000000000000 (M后面不够补0)
用十六进制表示就是:0x40 b0 00 00 (四个二进制位为一个十六进制数)
PS:小端存储,反过来读。
二、浮点数的读取
1.E不全为1,不全为0:
符号位为1取负数,为0取正数,指数E减去127,M前面加上1.xxxx。
2.E全为0:
这里规定浮点的指数就是 1-127=-126,M还原为0.xxxxx(前面不用加上1)。当把这个指数带入到浮点数中去时,就会发现 1/2^126,是个非常小的数无线接近于0,计算机无法表达。就规定
E全为0时,浮点数就是±0
3.E全为1时:
E全为1时,就是 1111 1111 等于255,原来的指数就是128,把指数128带入,2*2^128,要知道2的32次方就已经是四十亿多了。计算也无法表达,所以规定
E全为1时,浮点数根据符号位为正无穷和负无穷
。
4.解析代码
9 以整数的类型存储在内存中的二进制序列是:
00000000 00000000 00000000 00001001(正数原码就是补码)
以浮点数读取则:0 00000000 00000000000000000001001
S=0,E=-126,M=00000000000000000001001
科学计数法:(-1)^0 * 1.001*2^(-20) * 2^(-126)=1.001*2^(-146) 非常小无线接近于0
也可以直接因为E全为0,所以以浮点数读出来就是0
——————————————————————————————————————————–
9.0 二进制:1001.0
科学计数法:(-1)^0 * 1.001*2^3 S=0,M=001,E=3 (3+127=130 1000 0010)
以浮点型在内存中存储:0 10000010 00100000000000000000
以整数的方式读取:0100 0001 0001 0000 0000 0000 0000 0000 符号位为0,认为是正数,整数的补码等于原码。
2^30+2^24+2^20 = 1,091,567,616
拓展:
double(双精度浮点数)类型跟 float 类型存储的方式差不多,不过double是8字节,64比特位,E是11位(指数存在内存里加 1023 ),M是52位。
浮点数转换为二进制数
(计算转换,不是在内存中的存储):
一个小数:134.375
PS:整数部分商为0后,二进制是余数从下往上排列(
前面的0可以省略,后面的0不能省略
)。小数部分只计算小数点后面的小数,当小数为0时,二进制为个位的数从上往下排列(
后面的0可以省略,前面的0不能省略
)。
发现和计算机中存储的一样,说明上面的转换二进制的方法是正确的。
PS:3.14这个浮点数小数点后面是很长的一串0和1的组合,所以会发现浮点数其实是有精度的,在计算机中并不是很多的浮点数都是精确表示,大多都是四舍五入。