上一篇主要谈论了,计算机中为什么要有数据,以及数据为什么具有多样性,并提到一部分,整型是如何存入内存当中的。
而,这一篇主要是介绍浮点型在内存中的存储方式、以及运算。
目录
1.什么是浮点型数据?
简单来说,浮点数指的就是我们平常生活中见的小数。比如1.2、5.2、6.03等等,这些都是小数。区别于整型,当遇到这类数时,计算机仍然需要一定的类型,来存储这些小数。
(1)浮点型数据有哪些类型?
double与float的差异:
①在没有特定的强调下,一般小数的类型为double型:
②两者在取出时: 通常float ---> %f
double--->%lf
③所能开辟的空间:
④double往往比float修饰的精度更高
以上,仅仅肤浅地了解了浮点类型。
2.浮点数是怎样储存在内存中的?
我们不妨试试看看
如下的题目:
如果诸位读者已经可以看出四个值的大小以及原因,也就不必再往下读,耽误诸位时间。
(1)浮点数的存储原则
原理: (-1)^s*M*2^E
S ==符号位 M==有效位 E==小数点后的位数
光看结论肯定很枯燥也难理解,接下来我们不妨小实操一下。
十进制数:5.5
二进制数: 101.1
注:恐怕会有难以理解小数点后的0.5,怎么以二进制数表示。
我们可以想想,小数点前一位是2^0, 因此再下一位便可以推论出2^(-1)。
也可附上换算图(以供参考):
我们擅长用十进制的科学计数法,如122 可以写出----1.22* 10^2
于是,换算过来二进制科学计数法也同样如此:1.011*2^2
换算出:1.011*2^2 就不难和上述公式进行套用。
此刻可以分析出:S=0(因为5.5是正数) M=1.011 E=2(二的次方) 。
内存的浮点数(内存怎么给S M E进行分配):
根据国际标准IEEE:
对于不同的类型,S E M占内存空间的大小不同~
double型: 64 bit
float型: 32 bit
同时:
IEEE 754对有效数字M和指数E,还有一些特别规定:
①1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形式,其中xxxxxx表示小数部分。
②关于E的三种情况~~
一.E不全为0或1
E的暂时值,浮点型存入时,不能简单地取决于2后面有几次:
对于double而言: E(真实值)=E(本身的数) +1023
对于float而言: E(真实值)=E(本身的数) +128
当然,为了得到E的真实值,即,在浮点型的取出是,
对暂时值E-128(1023)即可。
二.E全为0
E全为0,意味着在浮点数取出的时候。
E+127=0,因此可以看出E=-127。(这是极小的接近于0 的数 2^(-127))
则:”有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数。
三.E全为1
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s)
有了上面的铺垫,我们就可以试着推算出,浮点型在内存中的储存。
(2)浮点型在内存中的储存
再对应二进制序列写到内存中:
注:此时E发生了变化
最后得到以下二进制序列:
0 100000001 01100000000000000000000
S E(8) M(23)
为了检验我们是否推论正确:
检验:
浮点型储存的方式也在这里,上面的题也就不难理解了。
3.浮点数的运算
(1)浮点数的精度损失
谈到浮点数的运算,我们有必要引入一个概念:
精度损失简单来说就是浮点数在运算的过程中会出现,真实值的改变。
下面是精度损失的例子:
也就是,因为精度的损失,造成了有违于我们正常的认识。
所以,上述结论可知,我们在进行浮点数的存储时,会发生精度损失。
(2)浮点数与浮点数的比较
因为存在精度损失,那么浮点数与浮点数的大小关系,是否能比较呢?
我们看看下面的代码:
很显然,我们期待的结果是x-0.9=y,然而事实上这是不等的~
于是乎,为了进行两个浮点数之间的大小比较,我们要引进一个新的概念,叫做EPS
注:EPS为极小的正数 类似于高数概念中的ε ,即大于0 的极小正数。
由此我们进行了如下的改造:
同样也可以优化成如下代码:
并会牵涉到以下的头文件: float.h math.h
关于EPS的定义,不仅仅有库函数的DBL_EPSILON、FLT_EPSILON
用户也可以进行自定义:
此时仍然可以达到我们的目的。
in conclusion,当我们要用两个浮点数进行大小的比较时,只需要让两者之差的绝对值<EPS即可~
(3)浮点数与0值的比较:
相信各位看到现在已经很疲惫了,毕竟学习的路是很枯燥、乏味的。因此我也不免,在这小逗一会儿。
https://www.bilibili.com/video/BV14p4y1q77g?spm_id_from=333.337.search-card.all.click
在这里,也祝诸君 能打赢学习上的硬仗,继续坚持无悔地走下去。
关于浮点数与0值的比较,其实同浮点数与浮点数之间的比较相差不大:
也可以做如下的优化:
可以看出,即便在如此小的x值下,仍然与0有清晰的大小关系。
①关乎DBL_EPSILON前加“=”的细节
当然,上面的代码,有时候也有如下的写法:
这样或许不容易直观地看出,因此我们对代码进行如下的修改:
前文已经赘述,EPS为极小的正数而非0;
因此下面的式子应该成立:
X+DBL_EPSILON !=X;
X+0 =0;
因此,即便编译器并没有报错,但是以我的愚见,此处加上=,其实不妥。
总结:
①double与float的对于浮点型数据的差异
②浮点数的储存原则
③浮点数储存存在精度损失
④浮点数不能用==比较
⑤浮点数之间比较两者的大小,则需要借助绝对值
⑥<=的细节
谢谢您的留步,阅读。祝你好运~陌生人