浮点数的存储

IEEE二进制浮点数算术标准IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU浮点运算器所采用。这个标准定义了表示浮点数的格式(包括负零-0)与反常值(denormal number)),一些特殊数值(无穷(Inf)与非数值(NaN)),以及这些数值的“浮点数运算符”;它也指明了四种数值舍入规则和五种例外状况(包括例外发生的时机与处理方式)。--------------百度百科

一、浮点数的存储方式

数据类型内存大小)内存分配指数偏移指数位范围精度
float32位

符号位(s)1位

指数位(E)8位

有效数字(M)23位

+127[0,255]小数点后6位
double64位

符号位(s)1位

指数位(E)11位

有效数字(M)52位

+1023[0,2047]小数点后15位

任意一个浮点数都可以表现为以下形式:

  1. (-1)^s表示符号位,s为0表示正,s为1表示负
  2. 2^E表示指数位
  3. M表示有效数字,大于等于1,小于2。

关于M和E在存储时有另外的要求:

       因为1<= M <2,所以M都写成1.xxxx的形式,所以计算机在存储M时,默认第一位总是为1,在存储时就会将这个1舍去,只保留后面的小数部分,在读取时再将1加上去,如下例 1.011,只保存011,这样可以多保留一位有效数字,如float型,M只占据23位,将1省去后,可以保留24位有效数字,精度更高。

对于E来说,首先E是一个无符号整数,是(unsigned int)。取值范围如上表所述,E为8位,它的取值范围为0-255,E为11位,它的取值范围为0~2047。但是,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数 ,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。称作指数偏移。
例:2^2的E是2,所以保存成为float型,必须保存成2+127=129,即10000001。

然后,指数E还可以再分成三种情况:
(1)E不全为0或不全为1
   这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实
  值,再将有效数字M加上第一位的1

(2)E全为0

   这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第一位的1,     而是还原为0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。

(3)E全为1
  这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);

计算机是按照如下方式去存储浮点数的:

单精度:第一位 符号位(s);第二位到第九位 数位(E);余下23位 有数字(M)

同理可得双精度,就不加以赘述了。

举例:十进制的5.5转化为二进制是101.1 = 1.011*2^2,按照上述表现形式可得

(-1)^0 * 1.011 * 2^2 即 s = 0 ,M= 1.011, E= 2;

存储时E要加上127 即 2+127 = 129 = 10000001

完整二进制表示为:

0 10000001 01100000000000000000000

十进制的 -5.5转化为二进制 -101.1 = 1.011*2^2 同理可得 :(-1)^1 * 1.011*2 ^2

即 s = 0,M= 1.011,E = 2.

同理 二进制表示为:

1 10000001 01100000000000000000000

验证代码:

#define  _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
	int n = 9;
	float* pFloat = (float*)&n;//因为&n是int* 所以加个强制类型转换 float*
	printf("n的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);
	*pFloat = 9.0;
	printf("num的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);
	return 0;
}

运行结果:

我们可以看到,同样的值,我们以不同的形式打印,得出来的结果大不相同。原因就是浮点型的存储和整型的存储时不一样的。我们用上述知识点分析一下结果由来:

1、n = 9 ;打印:n的值为9,整型赋值,整型拿出所以是9

2、*pFloat的值为0.000000 ,因为n =9 的二进制表示为 00000000000000000000000000001001

但是他是用浮点型的视角去看的,所以按照浮点数的存储方式解读就是:

s = 0; E= 00000000 ;M = 00000000000000000001001(E全为0的情况)

E的真实值:1-127=126 ;M= 0.00000000000000000001001

所以浮点数A= (-1)^0 * 0.00000000000000000001001 * 2 *(-126)而单精度浮点型只到读取小数点后6位,所以打印0.000000。

3、num的值为 :1091567616。*pFloat = 9.0 转为二进制 1001 = (-1)^0*1.001 * 2^3

s = 0; M =1. 001;E = 3;  ---> M = 00100000000000000000000 ; E= 3+127 = 130 = 10000010;

二进制表示:01000001000100000000000000000000 。将其作为整数转为十进制打印出来就是1091567616。

4、*pFloat的值为:9.000000.浮点型存入,浮点型打印所以是9.000000.

以上就是我关于浮点型存储知识的一些理解,取经于b站比特鹏哥的C语言视频,自己做了一些总结,巩固一下所学内容,小白学习,如有缺漏,敬请指出。

 

  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值