2.3 浮点数的表示和运算
1.浮点数尾数的表示
1.阶码(E):
反映数值大小;
反映浮点数的表示范围及小数点的实际位置;
常用补码或移码表示的定点整数;
2.尾数(M):
反映精度;常用原码或补码表示的定点小数
浮点数的真值:N=R^E×M,阶码的底(称为基数)R通常为2
例:若阶码和尾数均用补码表示,求a,b的真值
a=0,01;1.1001 (分号前的是阶码,分号后的是尾数,逗号前面的是符号位)
b=0,10;0.01001
a: 阶码:+1,尾数=-0.0111(二进制)
b: 阶码:+2,尾数=+0.01001(二进制)
a的真值为-0.0111×2=-0.111
b的真值为+0.01001×2^2=+1.001
×2的几次就相当于小数点向右移几位
2.浮点数尾数的规格化
上述例子中b的尾数为+0.01001,在存储时可以存储为0 01001,第一个0是符号位,若只能存储5位,最后一位就会丢失;可以考虑规格化让它的精度更高
此时符号位后第一位是无效位,可以让尾数算术左移一位,阶码减一,此时最高位就是有效位,这就叫作左规
1.规格化浮点数尾数要求:
规定尾数的最高数值位必须是一个有效值
2.左规:
当浮点数运算的结果为非规格化时要进行规格化处理,将尾数算术左移一位,阶码减1
3.右规:
当浮点数运算的结果,尾数出现溢出(双符号位为01或者10)时,将尾数算术右移1位,阶码加1
例:a=010;00.1100, b=010;00.1000,求a+b
a=22×00.1100,b=22×00.1000
a+b=2^2×(00.1100+00.1000)
=2^2×01.0100 (此时需要右规)
=2^3×00.1010
注:采用“双符号位”,当溢出发生时,可以挽救。更高的符号位是正确的符号位
3.规格化浮点数的特点
1.用原码表示的尾数进行规格化:
正数为0.1XX…X的形式,其最大值表示为0.11…1;最小值表示为0.10…0
尾数的表示范围为1/2≤M≤(1-2^(-n))
负数为1.1XX…X的形式,其最大值表示为1.10...0;最小值表示为1.11...1。 这个前面的1是符号位
尾数的表示范围为-(1-2^(-n))≤M≤-1/2
2.用补码表示的尾数进行规格化:
正数为0.1XX…X的形式,其最大值表示为0.11…1;最小值表示为0.10…0
尾数的表示范围为1/2≤M≤(1-2^(-n))
负数为1.0XX…X的形式,其最大值表示为1.01...1;最小值表示为1.00...0。 这个前面的1是符号位
尾数的表示范围为-1≤M≤-(1/2+2^(-n))
例:某浮点数的阶码、尾数用补码表示,共4+8位:
0.110;1.1110100如何规格化?(注:补码算术左移,低位补0;补码算术右移,高位补符号位)
解:因为给出的尾数是负数,只能对其进行算术左移,因为如果右移,补的是1,无法满足补码规格化的要求;
于是就进行左移三位,变成1.0100000;左移三位相当于扩大三位,所以阶码要减3,原来是0.110是6,减3就为0.011
3.浮点数的表示范围
负上溢|可表示的负数| 负下溢 |||零||| 正下溢 |可表示的正数|正上溢
若阶码为3位,那么阶码最小为-4,若尾数为0.1那么最小的正数就为0.00001,如果要表示的数比这个还小,就出现了正下溢
如果出现正下溢和负下溢的情况,一般会把这种情况当作机器数的0进行处理
如果出现正上溢或负上溢的情况,会抛出一个异常或者中断,和后面的中断知识会有所联系
4.IEEE754标准
1.移码
移码:在补码的基础上将符号位取反。注:移码只能用于表示整数
移码的定义:移码=真值+偏置值;偏置值一般取2(n-1),也可以取其他值,例如2(n-1)-1
例:若有8位数来表示一个值,此时的偏置值为2^7=128=1000 0000B
真值=-127=-111 1111B 移码=1000 0000+(-111 1111)=0000 0001
真值=-3=-11B 移码=1000 0000 +(-11B)=0111 1101
不同的偏置值会对应不同的移码
真值-128=-1000 0000B
移码=-1000 0000+0111 1111=1111 1111 ;会向更高位借一位(?)
2.IEEE 754标准
格式:ms(数符) || E(阶码,用移码表示)||M(尾数部分,用原码表示)
Ms(数符) | E(阶码,用移码表示) | M(尾数部分,用原码表示) |
---|
浮点数格式
短浮点数(单精度浮点数);长浮点数(双精度浮点数)
类型 | 数符(位数) | 阶码(位数) | 尾数数值(位数) | 总位数 | 偏置值(HEX) | 偏置值(DEC) |
---|---|---|---|---|---|---|
短浮点数(float) | 1 | 8 | 23 | 32 | 7FH | 127 |
长浮点数(double) | 1 | 11 | 52 | 64 | 3FFH | 1023 |
临时浮点数(long double) | 1 | 15 | 64 | 80 | 3FFFH | 16383 |
偏置值为2^(n-1)-1,阶码真值=移码-偏移量;计算真值时,可以将移码当作无符号数直接减去偏置值
尾数部分隐藏表示最高位的1,表示尾数为1.M
8位阶码的正常范围为-126-127,阶码全1和全0其他用处
规格化的短浮点数的真值:(-1)s×1.M×2(E-127)
规格化的长浮点数的真值:(-1)s×1.M×2(E-1023)
例1:将十进制数-0.75转换为IEEE 754的单精度浮点数格式表示。
解:(-0.75)D=(-0.11)B=(-1.1)B×2^(-1)
数符=1
尾数部分=.100000.....(隐含最高位为1)
阶码真值=-1,偏置值为127
移码=-1+127=126=0111 1110B
故-0.75为 1 01111110 1000...(共32位,尾数23位)
例2:IEEE 754的单精度浮点数C0 A0 00 00 H的值是多少
C0 A0 00 00 H -->> 1100 0000 1010 0000 0000 0000 0000 0000
数符:1 阶码:10000001 尾数:010 0000 0000 0000 0000 0000
数符为1表示是一个负数;尾数部分是.0100......(隐含最高位为1)说明真值=(1.01)B
移码为10000001,看作无符号数是129D
阶码真值=移码-偏置值=129-127=2D
故浮点数的真值=(-1.01)B×2^2=-1.25×4=-5.0
3.IEEE 754标准的表示范围
单精度浮点型能够表示的最小绝对值和最大绝对值
最小绝对值:尾数全为0,阶码最小值为-126,对应移码机器数为0000 0001,此时整体的真值为(1.0)B×2^(-126)
最大绝对值:尾数全为1,阶码最大值为127,对应移码机器数为1111 1110,此时整体的真值为(1.11...11)B×2^(127)
格式 | 规格化的最小绝对值 | 规格化的最大绝对值 |
---|---|---|
单精度 | E=1,M=0: 1.0×2(1-127)=2(-126) | E=254,M=.11...1: 1.11...1×2(254-127)=2127×(2-2^(-23)) |
双精度 | E=1,M=0: 1.0×2(1-1023)=2(-1022) | E=2026,M=.11...1: 1.11...1×2(2026-1023)=21023×(2-2^(-52)) |
上面表格中的这个阶码,是把它当作无符号数时的值,下面也是把E当作无符号数时候的值
阶码全为0的特殊情况:
(1)阶码E全为0,尾数M不全为0,表示非规格化的小数±(0.XX...XX)×2^(-126)
(2)阶码E全为0,尾数M全为0,表示真值±0(根据数符位决定是正0还是负0)
在(1)中和规划化小数不同的就是隐含最高位为0,并且阶码真值固定为-126
只有1≤E≤254时,真值=(-1)s×1.M×2(E-127)
阶码全为1的特殊情况:
(1)阶码E全为1,尾数M全为0,表示无穷大±∞, ----当运算结果出现正上溢或负上溢的时候,机器通常会把结果记为正无穷或者负无穷
(2)阶码E全为1,尾数M不全为0,表示非数值“NaN”(Not a Number) ----如:0/0,∞-∞等非法运算的结果就是NaN
4.总结
由浮点数确定真值(阶码不全为0也不全为1):
- 根据“这个浮点数”确定数符,阶码,尾数的分布
- 确定尾数1.M(注意补充最高位隐含的1)
- 确定阶码的真值=移码-偏置值(可将移码看作无符号数,用无符号数的值-偏置值)
- (-1)s×1.M×2(E-偏置值)
5.浮点数的加减运算
1.浮点数加减运算步骤
(1)对阶(小阶对大阶)
为什么是小阶对大阶?如果是大阶对小阶的话,小数点前面可能不止一位,用计算机去表示这样的一个数会比较麻烦
(2)尾数加减
(3)规格化
(4)舍入
为什么需要舍入:因为在计算机中浮点数存储位数是有限制的,所以尾数的位数也是有限制的,当尾数加减后的结果超出尾数位数的限制时,就要进行舍入
不同的舍入规则:
- 可以将多余的位数直接舍去
- 若舍去部分不为0,则末位+1(入1)
- 四舍五入原则
(5)判溢出
假设给阶码规定就只有2位来进行表示,那么如果运算后阶码超出范围,则溢出
如:9.99999×1099+9.99999×1099=19.99998×1099=1.99999×10100(这里是保留了6位尾数),此时阶码超过2位,发生溢出(注:尾数溢出未必是真的溢出,也许可以通过(3)规格化(4)舍入这两步来进行调整)
例1:求1.23456×1012+2.34567×1010(这个例子是十进制的)
(1)对阶:1.23456×1012+0.0234567×1012
(2)尾数加减:1.2580167×10^12
(3)规格化,这里的例子不需要进行规格化,但是如果尾数加减后出现0.001234×1012这种情况时,需要“左规”;或者出现12.34567×1012这种情况时,需要进行“右规”
(4)这里若只能保留6位有效尾数,可以根据舍入规则来进行舍入,譬如直接舍入(多余位直接舍去)成1.25801×10^12
(5)判断溢出的话,这里是没有溢出的
例2:已知十进制数X=-5/256、Y=+59/1024,按机器补码浮点运算规则计算X-Y,结果用二进制表示,浮点数格式如下:阶符取2位,阶码取3位,数符取2位,尾数取9位
X=-5D×(1/256)=-101B×2(-8)=-0.101B×2(-5)=-0.101B×2^(-101B)
Y=+59D×(1/1024)=+111011B×2(-10)=+0.111011B×2(-4)=+0.111011B×2^(-100)
再转化成补码:X=11011,11.011000000;Y=11100,00.111011000
再根据上面的浮点数加减运算步骤进行加减:
(1)对阶 使两个数的阶码相等,小阶对大阶,尾数右移一位,阶码加1
- 求阶差:[△E]=11011+[-Y补]=11011+00100=11111=-1,故X的阶码比Y的阶码小1;
- 对阶,X=11011,11.011000000->11100,11.101100000
(2)尾数加减 -Y=11100,11.000101000
X-Y=11.101100000+11.000101000=11100,10.110001000
(3)规格化
两位符号位不同,表明尾数溢出,所以要进行算术右移,右移1位,阶码加一
X-Y=11101,11.011000100
(4)舍入
无舍入
(5)判溢出
阶码无溢出 ,最终结果为2^(-3)×(-1001111B) ----记得要将规格化之后的补码再转回原码
2.浮点数的加减运算-舍入
“0”舍“1”入法:在尾数右移时,被移去的最高数值位为0,则舍去;被移去的最高数值位为1,则在尾数的末位加1.但是这样加1后可能会使尾数再次溢出,此时需再做一次右规。
恒置“1”法:尾数右移时,不论丢掉的最高数值位是“1”还是“0”,都使右移后的尾数末位恒置“1”。这种方法会有使尾数变大和变小的两种可能。
如:若加减结果为11100,10.110001011
0舍1入:11100,10.11000101 1->11101,11.011000110
恒置1:11100,10.11000101 1->11101,11.011000101
在规格化步骤中,右规就会遇到舍入的问题
6.强制类型转换
类型 | 16位机器 | 32位机器 | 64位机器 |
---|---|---|---|
char | 8 | 8 | 8 |
short | 16 | 16 | 16 |
int | 16 | 32 | 32 |
long | 32 | 32 | 64 |
long long | 64 | 64 | 64 |
float | 16 | 32 | 32 |
double | 64 | 64 | 64 |
char->int->long->double
float->double
范围、精度从小到大,转换过程没有损失(这里默认是32位机器)
32位
int:表示整数,范围-231~231-1,有效数字31位
float:表示整数及小数,范围±[2(-126)~2127×(2-2^(-23))],有效数字23+1=24位
int->float:可能损失精度
float->int:可能溢出以及损失精度
- 浮点数是小数,转int小数部分丢失
- 浮点数太大,超出int表示范围
7.做题总结
1.8421码是十进制数的编码
2.正数的原码,反码,补码都一样
3.程序中的数字中带有E(e),表示乘10的多少次方
例:1.5678e3就表示1.5678×103;1.5e100=1.5×10100
4.对阶时,尾数的右移要带着隐含位的1一起右移
标签:表示,阶码,真值,运算,尾数,浮点数,移码,数据,规格化 From: https://www.cnblogs.com/Jinx8823/p/17380181.html