浮点数的表示
S:符号
M:尾数,定点原码小数表示
R:基数,可取2的幂数,这里R=2
E:阶码
阶码的值反映浮点数小数点的实际位置
例如:a=0,01;1.1001,其阶码和尾数均由补码表示
a的阶码对应真值+1,a的尾数对应真值-0.0111
a的真值=2^1 x (-0.0111)=-0.111 小数点在尾数的基础上右移一位
阶码的位数反映浮点数的表示范围
假设阶码只有3bit,只能在尾数的基础上左移3位或右移4位,
尾数的位数反映浮点数的精度
例如同上a=0,01;1.1001,但此时尾数从1.1001扩展为1.10010011,显然提高了a的精度
浮点数的规格化
什么是规格化?
规格化就是在存储空间不变的前提下尽可能提高浮点数的精度
为什么需要规格化?
当存储空间只有1B,尾数只有5bit,而尾数是+0.01001,由于这个0作为尾数的最高位是无效位丧失精度
如何规格化?
处理方法:尾数算数左移1位,阶码减1,直到最高位是有效位(左规)
·左规:当浮点数的运算结果非规格化(最高位非有效位),尾数算术左移一位,阶码减一
·右规:当浮点数的运算结果溢出(双符号位出现01/10),尾数算术右移一位,阶码加一(算术移位时,双符号位补码符号最左边补0/1取决于移位前最左边的符号位是0/1)
规格化浮点数的特点
疑问:为什么当尾数用补码表示且尾数是负数时,最高数值位是0?
只是为了方便计算机判断该尾数是否进行规格化
以尾数为补码表示的 a=0,110;1.1110 1000为例
根据规格化的特点,当用补码表示尾数时,符号位与最高位相反,这里需要将尾数算数左移3bit,同时需要将阶码-3;得到规格化后的数据:0,011;1.0100 0000
IEEE标准
前导知识:移码
移码=真值+偏置值
正常移码的偏置值是,例如8位移码的偏置值为1000 0000
iEEE标准的补码的偏置值为,例如8位移码的偏置值为0111 1111,如图所示:
1. 需牢记float和double的数符,阶码,尾数的位数
2. 注意尾数部分是用原码表示,最高位隐含为1,所以需要1.M开头
例1:将十进制数-0.75转换为IEEE的单精度浮点数格式
需要对(-0.11)进行规格化处理成(-1.1)*2^(-1)
数符:1
阶码真值:-1,则对应移码:-1+127D=0111 1110
IEEE表示:1 0111 1110 10000.....000 // 因为最高隐含位为1,所以此处是1而不是11
例2:IEEE754的单精度浮点数C0 A0 00 00H对应的十进制值是多少?
C0 A0 00 00H-> 1100 0000 1010 0000 0000 0000 0000 0000
首先1可知是负数
尾数部分,由于最高位隐含为1,所以尾数真值为(1.01)2
阶码部分,真值=移码-偏置值=1000 0001 - 0111 1111=(2)10
浮点数真值:
3.阶码真值的表示范围:-126~127
即移码的1111 1111和0000 0000有另外的用途:
当阶码E全为0,尾数M不全为0时,表示非规格化小数,即最高位为0,且阶码固定视为-126
当阶码E全为0,尾数M全为0时,表示真值±0;
当阶码E全为1,尾数M全为0时,表示±∞;
当阶码E全为1,尾数M不全为0时,表示Not a Number(NaN);
浮点数的加减运算
先以10进制的加减运算为例,初步理解各步骤的含义
1. 为什么是小阶向大阶靠齐?
之所以这样做是因为若大阶对小阶,则尾数的数值部分的高位需移出,而小阶对大阶移出的是尾数的数值部分的低位,这样精度损失更小。
2.为什么要进行规格化处理?
在进行尾数加减后可能造成尾数的溢出,尾数双符号位变成01 / 10的形式,此时就需要进行规格化处理
3. 当进行规格化处理的右规时,最后一位要被移出的是1时该怎么处理?
·0舍1入法: 被移出的数值位为0,不做操作;被移除的数值位为1,在尾数的末尾加1,加1这一操作很有可能会再一次造成尾数溢出,又需要做一次右规
·恒置1法:不论右移出的数值位是多少,让右移后的尾数保证是1即可
4. 如何进行溢出判断?
当阶码的双符号位为01时,发生上溢产生异常,阶码的双符号位为10时,下溢出,按0处理
用下面例题讲解
首先将题目给出的X,Y转换成规格化后的浮点数格式
对阶时注意小阶向大阶看齐,求阶差时,将阶码部分的X-Y转换为X+(-Y);结果为-n,则X+n,并将尾数右移n位(理解:比如X的阶码-5,Y的阶码-4,那么X-Y=-1,则X应该加1,而X+1相当于尾数乘以2^1也就是左移了一位,那么为了保证数据的一致,尾数就需要右移一位)
尾数加减完,需要进行规格化:X-Y=11100,10.110001000,需要进行右规(尾数右移,阶码加1)
右移时,最后一位需要考虑舍入情况
最后根据阶符判断溢出情况
强制类型转换:
为什么int是32转换为float32位会损失精度?
因为float中只有1(最高位隐含为1)+23个=24有效数值,而int有31个有效数值位,转换过程损失精度
那为什么反过来float转int可能溢出或损失精度?
int只会取float的整数部分
int转换为float的详细讲解可见:C/C++ - int转float时精度损失问题_c++ int 转 float-CSDN博客