第2章-数据的表示和运算

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

不同的偏置值会对应不同的移码

image-20230429123422766

真值-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. 根据“这个浮点数”确定数符,阶码,尾数的分布
  2. 确定尾数1.M(注意补充最高位隐含的1)
  3. 确定阶码的真值=移码-偏置值(可将移码看作无符号数,用无符号数的值-偏置值)
  4. (-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

  1. 求阶差:[△E]=11011+[-Y补]=11011+00100=11111=-1,故X的阶码比Y的阶码小1;
  2. 对阶,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一起右移

posted @ 2023-05-07 21:09  Jinx8823  阅读(470)  评论(0编辑  收藏  举报