浮点数在内存中的存储规则

  • Post author:
  • Post category:其他


引子:

阅读一段代码:

    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的组合,所以会发现浮点数其实是有精度的,在计算机中并不是很多的浮点数都是精确表示,大多都是四舍五入。



版权声明:本文为weixin_45423515原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。