计组学习笔记(⼀):浮点数的表⽰和运算
最近学习计算机组成原理,遇到许多疑难问题,接下来写⼀写我在学习浮点数⽅⾯知识的理解,在巩固的同时也⽅便⽇后的复习。
⼀、浮点数的表⽰
1、浮点数的表⽰格式
浮点数,顾名思义,就是⼩数点不固定的数。计算机中,根据⼩数点位置是否固定,分为两种数据格式,⼀种就是这个,⼩数点不固定,另⼀种是定点数,⼩数点是固定的。
书上科学地对浮点数表⽰法的定义是,以适当的形式将⽐例因⼦表⽰在数据中,让⼩数点的位置根据需要⽽浮动。我们计算机的容量有限,不可能对每个数都⽤特别多的位数来表⽰,⽐如说2×10^99,这种⾮常⼤的数不可能⽤定点数来表⽰,所以呢利⽤浮点数就可以在位数有限的情况下扩⼤数的表⽰范围,同时能保持⼀定的有效精度。
通常情况下,浮点数表⽰为:N = r^E × M
式⼦⾥⾯r是浮点数阶码的底在计算机中是隐含的,通常情况下r=2。E和M都是带符号的定点数,E叫做阶码,M叫做尾数。其中E的⼤⼩越⼤,能表⽰的数范围越⼤,M的位数越⼤,数的有效精度越⾼。
简单地举⼀个例⼦,1.111×2^100这⾥⾯1.111就是尾数,100就是阶码,显然这⾥阶码占的位数为3位,尾数占的位数是4位,假如阶码占的位数有4位,位数占的位数是3位(阶码和尾数所占位数总和不变),那么这个数就只能表⽰为1.11×2^0100,显然能表⽰的数的范围变⼤了,就这个例⼦来说原来尾数1.111转变为1.11损失了0.001,这就是精度的损失。
浮点数的⼀般格式:
这⾥J是阶符,表⽰阶码的符号,S是数符,表⽰浮点数的符号,阶符J和阶码的m位合起来表⽰浮点数的表⽰范围和⼩数点的实际位置,n 位尾数反映了浮点数的精度。
2、浮点数的规格化
为什么要进⾏浮点数的规格化呢,我们知道了浮点数的⼀般格式,同⼀个浮点数可以有很多表现形式,⽐如1.111×2^3,还可以表⽰为0.1111×2^4,还可以表⽰为11.11×2^2,那我们总不能任意地表⽰⼀个数吧,另外还有⼀个问题就是,如果尾数位数只有4位,我们想要表⽰同⼀个数1111采取两种⽅法,⼀个是 0.0111x2^5 和 0.1111×2^4(⼆者最⾼为是数符位S),我们可以很清晰地看到,如果采⽤阶码为5的⽅法,我们损失了⼀位精度,阶码为4的⽅法表⽰这个数更为精确。
所以,为了提⾼运算精度,就要充分利⽤尾数的有效数位,也就是浮点数的规格化,即规定尾数的最⾼数位必须是⼀个有效值。⾮规格化数转变为规格化数,转变过程就是通过调整尾数和阶码的⼤⼩,使尾数最⾼位保证是⼀个有效值。通常有两种规格化操作:
左规:当浮点数运算结果是⾮规格化数的时候,要进⾏规格化操作,将尾数算术左移⼀位,阶码减1(基数为2时),左规操作可能要进⾏多次。
右规:当浮点数运算结果尾数出现溢出的时候,将尾数算术右移⼀位,阶码加1。需要右规操作的时候只需要操作⼀次。
规格化浮点数的尾数M的绝对值应该满⾜这样的关系:1/r ≤ |M| ≤ 1(r就是我们的阶码的底,也是基数)。
以r=2为例:
1、原码尾数规格化后:正数为0.1xxxxxx形式,最⼤值为1;最⼩值为0。负数为1.1xxxxxx形式,最⼤值表⽰为
浮点数的基数什么意思
0;最⼩值表⽰为1。
2、补码尾数规格化后:正数同原码正数。负数为1.0xxxxxx形式,最⼤值表⽰为1;最⼩值表⽰为0。
需要注意的是基数,刚刚是以基数为2时的规格化形式,补码规格化数的尾数最⾼位⼀定与尾数符号位相反。基数不同的时候,规格化的形式不同,当基数为4时,原码规格化形式的尾数最⾼两位不全为0;基数为8时,原码规格化形式的尾数最⾼三位不全为0。
如何判断⼀个浮点数是否是规格化数:规格化浮点数的尾数⼩数点后的第⼀位⼀定是个⾮零的数。因此对于原码编码的尾数来说,只要看尾数的第⼀位是否为1就⾏;对于补码表⽰的尾数,只要看符号位和尾数最⾼位是否相反。(IEEE 754标准的浮点数尾数是⽤原码编码的)
3、IEEE 754标准
IEEE 754标准采⽤的浮点数的格式:
ms为数符,表⽰浮点数的符号,E为阶码部分,⽤移码表⽰,M是尾数部分,⽤原码表⽰。
IEEE 754标准规定常⽤的浮点数格式有短浮点数(单精度、float)、长浮点数(双精度、double型)
、临时浮点数。
短浮点数数符占1位;阶码占8位,以2为底,⽤移码表⽰,阶码偏置值为127(阶码全1表⽰⽆限⼤,E的范围是1~254,空出全0表⽰⾮规格化数);尾数部分为23位。
长浮点数数符占1位;阶码占11位,以2为底,⽤移码表⽰,阶码偏置值为1023(阶码全1表⽰⽆限⼤,E的范围是1~2046,空出全0表⽰⾮规格化数);尾数部分为52位。
在IEEE754标准中长浮点数和短浮点数的尾数采⽤隐藏位策略的原码表⽰,什么意思呢。举个例⼦来说,以短浮点数为例,尾数占23位。我们知道,规格化浮点数后,尾数最⾼位⼀定是⼀位有效值,对于⼆进制浮点数来说,尾数最⾼位⼀定是1,那么我们为了充分利⽤资源,既然最⾼位⼀定是1了,我们⼲脆就把它隐藏好了,因此尾数实际上是24位,在表⽰的时候尾数23位是纯⼩数。⽐如说⼗进制
12(1100),转化为⼆进制浮点数规格化后为1.1×2^3,这⾥我们就把整数部分的1 隐藏了,整数部分的1不存在23位尾数中,存的时候就是这样的32位:0  1000 0010  1000 0000 0000 0000 0000 000。
⼆、浮点数的加减运算
浮点数运算的特点是阶码运算和尾数运算分开来算。加减运算⼀律采⽤补码。具体运算分为以下⼏步。
1、对阶:对阶的⽬的是让两个数⼩数点的位置看齐,使这两个数的阶码相等。显然1.1×2^3和1.1×2^4是不能直接相加减的。原则是⼩阶向⼤阶看齐,像这个例⼦,就是1.1×2^3的尾数右移⼀位,阶码加⼀,直到两个数的阶码相等。
2、尾数求和:阶码对齐之后就可以直接按照定点数的加减法则运算尾数了。
3、规格化:尾数求和后的结果如果不是规格化数需要规格化,以双符号位运算为例的话,如果运算结果为正数,规格化的形式应该是,如果运算结果为负数,规格化后的形式应该是,不符合这种形式的数要进⾏左规或者右规的操作让其变成这种形式。(在尾数没有溢出的情况下,即尾数结果的双符号为不是10或01的时候,操作都是左规操作,左规操作可能不⽌进⾏⼀次,倘若双符号位为01或10则表明尾数已经溢出了,就要进⾏右规操作,右规只需要进⾏⼀次)
4、舍⼊:在对阶和右规的操作中,我们都是将尾数右移,阶码加⼀,由于我们的位数是有限的,在右移的操作过程中很有可能就将低位的尾数丢失了,这会引起误差和精度问题。常⽤的减⼩误差的⽅法有“0”舍“1”⼊法:即在尾数右移时,被移去的最⾼数值位为0则舍去,如果被移去的最⾼数值位为1则在尾数末位加1,如果加1之后⼜产⽣溢出则再右规操作⼀次。恒置“1”法:看名字就可以知道,⽆论丢掉的最⾼数值位是1还是0,都使右移后的尾数末位置1。这种⽅法可能使尾数变⼤或者变⼩。
5、溢出判断:既然定点数运算可能溢出,浮点数同样也会溢出,我们已经知道浮点数的表⽰⽅法和加
减运算规则,既然是溢出,那么肯定是超出了浮点数能表⽰的范围,浮点数的范围主要是由阶码决定的,如果运算结果规格化后阶码产⽣了溢出,那才是浮点数的溢出。浮点数的溢出与否是由阶码的符号决定的。以双符号位的补码为例,如果阶码的符号位出现01或10则说明阶码溢出了,01表⽰阶码⼤于最⼤阶码,上溢,进⼊中断处理;10表⽰阶码⼩于最下阶码,下溢,按机器零处理。(溢出时真值的符号位和⾼位符号位保持⼀致)还要注意的⼀点是尾数之和(差)可能会造成尾数的溢出,这并不代表整个的溢出,需要右规⼀次看阶码是否溢出才能判断。
以上便是我学习浮点数的时候结合书与⾃⼰的理解做出的总结,例⼦都是以基数为2时举的,如果有错误还望指明。