浮点数的储存

浮点数的储存

我们都知道整形在内存中是按照补码的形式储存的,但是浮点数的储存却和整数的截然不同,浮点数没有所谓是原反补并且浮点数的大小很多情况下不能直接比较,这是怎么一回事呢?

引子

c 复制代码
int main()
{
 int n = 9;
 float *pFloat = (float *)&n;
 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;
}

这是怎么回事呢?接下来得提到浮点数的储存了。

一.浮点数的三段式(S,E,M)

1.如何放入

根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式

(-1)^S * M * 2^E
(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位。

举例来说十进制的20.0写成二进制是10100.0,那么换成浮点数一般储存方式是(-1)^0*1.0100 *2 ^4 。相当于S=0,M=1.0100,E=4。简而言之就是前面的-1用来判断正负,后面全部转化为科学计数法。

再举个例子十进制的-25.5写成二进制是11001.1(注意小数点后第一位的权重是2的-1次方,也就是0.5)。那么转换为一般浮点数存储方式就是(-1)* 1 *1.1001 *2^4。也就是S=1,M=1.1001,E=4。

具体的放入方式


S和 M的储存

S是用来判断正负的,是正就存0是负就存1。M我们前面也提到过必须先转换成按2的科学计数法,也就是2>M>=1(其实也很好理解,毕竟二进制最大就是2嘛)。

IEEE 754规定,在计算机内部保存M时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的时候,只保存01,等到读取的时候,第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只23位,将第一位的1舍去以后,等于可以保存24位有效数字。

以上面的20.0为例,就相当于M=1.0100,只是存入了01000。

E的储存

首先要明确的是E是无符号整数,这意味着,如果E为8位,它的取值范围为0~ 255;如果E为11位,它的取值范围为0~2047。

但在实际中我们知道E是可能出现负数的(例如0.5写成科学计数法是1.0 * 2^-1 ,那么此时E=-1)。所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^10的E是10,所以保存成32位浮点数时,必须保存成10+127=137,即0001001。

一个例子

2.如何取出

取出主要分为三种情况。

一般情况(E不为全0或全1)

此时就是如何存入就如何取出。

例子

E全为0

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

E全为1

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

二.为什么浮点数不能直接比较

可以发现我之前写的数全是20.0,·25.5这种能够被2除尽的数。那么如果是3.14这种数怎么写呢?

这是不能精确的转换为二进制,3.14中3可以用11表示但0.14呢?我们只能近似的写成001...010110...无论我们写多少为都不能精确的表达0.14。但如果写的位数越多那么就越接近0.14这个值,这也是为什么double比float精度高的原因。

三.解释第一个问题

二进制序列本身是没有任何意义的,当我们用不同方式去看这个序列时,该序列才被赋予了特定的含义。所以在使用时我们需要以什么方式存就以什么方式拿,不然会出现乱序。

总结:浮点数存储就是先将其化为二进制序列,然后再换成科学计数法,之后再分别按S,E,M存入不够位数后面补0。

相关推荐
‘’林花谢了春红‘’34 分钟前
C++ list (链表)容器
c++·链表·list
----云烟----1 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024061 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
开心工作室_kaic1 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
向宇it1 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
武子康2 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
转世成为计算机大神2 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式
机器视觉知识推荐、就业指导2 小时前
C++设计模式:建造者模式(Builder) 房屋建造案例
c++
宅小海2 小时前
scala String
大数据·开发语言·scala
qq_327342732 小时前
Java实现离线身份证号码OCR识别
java·开发语言