vb double显示最大精度_[读书笔记]CSAPP:4[VB]浮点数据类型

视频地址:

【精校中英字幕】2015 CMU 15-213 CSAPP 深入理解计算机系统 课程视频_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com
1db9626f1fe626222b187bb15411d0f7.png

课件地址:

http://www.cs.cmu.edu/afs/cs/academic/class/15213-f15/www/lectures/04-float.pdf​www.cs.cmu.edu

对应于书本的2.4。

如有错误请指出,谢谢。


1 浮点数简介

浮点表示对形如

的有理数进行编码,比较适用于非常大的数字、非常接近0的数字。它常常不会太多关注运算的准确性,而是把实现的速度和简便性看得比数字精确性更重要。1985年提出了IEEE标准754,仔细制定了表示浮点数机器运算的标准,后续所有计算机都支持这个标准,极大提高了程序可移植性。

首先会介绍IEEE浮点表示方法,然后由于数字不能精确被表示,所以会介绍浮点数的舍入问题。最后介绍浮点数相关的运算。

2 IEEE浮点表示

IEEE浮点表示使用

表示数字。其中包含三部分:
  • 符号(Sign)s:用来确定V的正负性,当s=0时表示正数,s=1时表示负数。用一个单独的符号位直接进行编码。
  • 尾数(Significand)M: 是一个二进制小数,通常介于1和2之间的小数。使用k位二进制进行编码的小数。
  • 阶码(Exponent)E:对浮点数进行加权。使用n位进行编码的正数

C语言中有单精度精浮点数float,其中s=1、k=8、n=23;还有双精度浮点数double,其中s=1、k=11、n=52。

c5ade817793ee1faf83663bbba94132b.png

我们可以根据尾数和阶码的不同取值,将其分成三种情况:

  1. 规格化的值:
    时,
    ,其中
    ,由此能将E重新投影到正负值,并且能够和非规格化进行平滑;
    ,因为我们可以通过调整E使得
    ,所以通过这种形式将尾数变成
    的形式,就能获得额外的精度。g
    规格化数能够表示大范围的数。
  2. 非规格化的值:
    时,
    ,由此来保证和规格化值的连续性;
    非规格化数能够表示正负0以及趋近于0的数。
  3. 特殊值:当阶码全为1时,如果尾数全为0,则表示无穷,比如两个很大的数相乘,或除以0时;否则表示NaN(Not a Number),比如求-1的根号。

010afd97ebba88a6c73b1718f672bbec.png

4cfbb231c2b74797e021623dedf82f54.png

通过上面我们可以观察到几个现象

  1. 非规格数稠密地分布在靠近0的区域;
  2. 有些数的间隔是等距的,因为当exp值不变,在frac尾数区域进行增加会乘上相同的指数;
  3. 越大的数间隔越大,因为比较大的数,它的指数
    会比较大,使得每次变化量会比较大。

根据二进制编码计算数值:

  1. 计算
  2. 计算阶码的值exp和尾数的值frac
  3. 如果为规格化值,则
    ;如果为非规格化值,则
  4. 计算最终的值

我们以正数为例(s=0),说明几个比较特殊的值:

  • 0:只有非规格化才能表示0,exp和frac全部为0时,结果为0。
  • 最小的正非规格化数:
    是固定值,在frac取值范围内的最小值正数是
    ,则
    ,所以
  • 最大非规格化数:E还是固定值
    ,在frac取值范围内的最大值是
    ,则
    ,所以
  • 最小规格化数:exp的最小值为
    ,所以
    ;frac全0时,M取得最小值1,所以
  • 1:要表示1,则需要用规格化来表示,当frac全为0时,M=1,需要让E=0,则
    ,即exp为
  • 最大规格化数:exp的最大值为
    ,frac的最大值为全1,即
    ,所以
    ,所以

bfd96e8fc1c68017de8662d2e20b7940.png

IEEE设计的好处:

  1. 最大非规格化值
    和最小规格化值
    之间的幅度是
    ,是n位尾数所能表示的最小值,可以看成是
    光滑转变
  2. 从最小非规格化数到最大规格化数的位向量的变化是顺序的,和无符号整数的排序相同。所以可以用无符号数的排序函数来对浮点数进行排序注意:负无穷转化为无符号数进行比较时会有问题。

将十进制化为浮点数表示:

以12345为例,我们推算单精度浮点数的编码

  1. 计算
  2. 将12345化为二进制数
  3. 首先将二进制数其化成小于1的科学技术法
    ,很明显指数14不为
    ,所以是规格化数,所以将其转化为大于1的科学计数法
    ,所以
  4. 因为
    ,所以frac的编码为
    。因为
    ,所以
  5. 将frac和exp的二进制编码扩展到对应位数并拼接在一起,补上符号位就为最终结果

注意:要在exp前面补0,在frac后面补0。因为exp表示整数,frac表示小数。

对比无符号数的编码,我们可以发现:因为无符号数一定大于0,所以相同的数想用浮点数编码只能使用规范化数进行编码,而规范化数会将frac的最高有效位1去掉,所以无符号数的编码和浮点数编码,在frac部分是相似的,浮点数会少了最高有效位的1。而无符号数的其他部分就是0,而浮点数的其他部分是表示指数的编码。

3 浮点数舍入

浮点数由于有限的位数,所以对于真实值x,我们想要用一种系统的方法来找到能够用浮点数表示的“最接近的x”匹配值x',这个过程就称为舍入

常见的舍入方法有四种:向零舍入、向上舍入、向下舍入以及向偶数舍入。以十进制为例可以看以下表格

a68dd64196d729bf7fade807c9262442.png

其中比较特殊的是向偶数舍入:如果处于中间值,就朝着令最后一个有效位为偶数来舍入;否则朝着最近的值舍入。比如1.40,由于靠近1就朝1舍入;1.6靠近2就朝2舍入;1.50位于十进制的中间值,就朝着偶数舍入,所以为2。

向偶数舍入的意义:如果对一系列值进行向上舍入,则舍入后的平均值会比真实值更大;使用向下舍入,则舍入后的平均值会比真实值更小。通过向偶数舍入,每个值就有50%概率变大、50%概率变小,使得总的统计量保持较为稳定。

十进制的中间值为

,比这个中间值大就向上舍入,比这个中间值小就向下舍入,否则朝着偶数舍入。

而二进制的中间值是

,比如
就比中间值大,
就比中间值小。而且二进制中,当最后一个有效位为0时,为偶数。比如

f2550b2929a3d67eb427b33b8d0a03de.png
  • 10.00011:由于011比中间值小,所以直接向下舍入,为10.00
  • 10.00110:由于110比中间值大,所以直接向上舍入,为10.01
  • 10.11100:由于100为中间值,而10.11最后一个有效位1位奇数,所以向上舍入为偶数11.00
  • 10.10100:由于100为中间值,而10.10最后一个有效位0位偶数,所以直接向下舍入10.10

4 浮点数运算

浮点数运算无法直接通过在位向量上运算得到。

4.1 浮点数乘法

对于两个浮点数

,计算结果为
,其中
  • 如果
    ,就将frac右移一位,并对E加一。
  • 如果E超过了表示范围,就发生了溢出。
  • 如果M超过了表示范围,对frac进行舍入。

数学性质:

  • 可交换
  • 不可结合:可能出现溢出和不精确的舍入,比如
    ,而
  • 不可分配:如果分配了可能会出现NaN,比如
    ,而
  • 保证,只要
    ,则

4.2 浮点数加法

对于两个浮点数

,计算结果为
,其中s和M是对其后的运算结果,

0b186c8ccf2dee9edd634d12531e0dde.png
  • 如果
    ,则frac右移一位,并对E加1。
  • 如果
    ,则frac左移一位,并对E减1。
  • 如果E超过表示范围,就发生溢出。
  • 如果M超过表示范围,就对frac进行舍入。

数学性质:

  • 由于溢出,可能得到无穷之。
  • 可交换
  • 不可结合(由于舍入),因为较大的数和较小的数相加,由于舍入问题,会将较小的数舍入,比如
  • 除了无穷和NaN,存在加法逆元。
  • 满足单调性,如果
    ,则对于任意a、b和x,都有
    。NaN除外。无符号数和补码由于溢出会发生值的跳变,所以不满足单调性。

注意:需要考虑好清楚数值的范围,如果计算的数值范围变化很大,需要重新结合或改变运算顺序,避免由于溢出或舍入出现计算问题。

5 C中的浮点数

C中提供了floatdouble两种精度的浮点数。由于编码不同,所以在浮点数和整型数之间强制类型转换时,会修改编码,并且会出现溢出和舍入。

  • float/double转换成int:首先小数部分会被截断,也就是向0舍入。float的尾数部分为23字节,比int的32字节小,所以int可以精确表示float的整数部分,而double的尾数有52位,可能会出现舍入。并且当超过int的取值范围或NaN时,微处理器会指定
    为整数不确定值,即对应的
    ,所以一个很大的浮点数转化为int时,可能会出现负数。
  • int或float转换为double:double尾数有52位,而int只有32位,float只有23位,所以double会精确表示int和float,不会出现溢出和输入。
  • int转换为float:不会发生溢出,但是由于float尾数位数比较少,会出现舍入。
  • double转换为float:可能会出现溢出和舍入。

总结:超过数值表示范围,会发生溢出;尾数较短,会发生输入。


课堂作业:

5d5fee92640fb92139f9545c3a6c5994.png
  • x==(int)(float)x:int有32位,float尾数有23位,从int强制类型转换到float会出现舍入,所以错误。
  • x==(int)(double)x:int有32位,double尾数有52位,所以从int强制类型转换到float不会出现舍入,所以正确。
  • f==(float)(double)f:double的精度和范围都比float大,所以能够无损地从float强制类型转换到double,所以正确。
  • d==(double)(float)d:因为float的精度和范围都比double小,可能会出现溢出和输入,所以错误。
  • f==-(-f):因为只要改变一个符号位,所以正确。
  • 2/3==2/3.0: 因为2/3是int类型,会舍入变成0,而2/3.0是double类型,会得到数值,所以错误。
  • d<0.0推出((d*2)<0.0):乘2相当于exp加一,如果出现溢出,也是无穷小,所以正确。
  • d>f推出-f>-d: 只要改变一个符号位,所以正确。
  • d*d>=0.0: 正确。
  • (d+f)-d==f:不符合结合律,可能会出现舍入和溢出。

接下来会完成课后练习题,然后完成Lab 。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值