计算机中的数(一):数在计算机中的表示

参考资料:

唐朔飞《计算机组成原理》高等教育出版社
张代远《计算机组成原理教程 第二版》清华大学出版社

 
定点和浮点
定点格式
所谓定点格式,即约定机器中所有数据的小数点位置是固定不变的。在计算机中通常采用两种简单的约定:约定小数点的位置固定在数据的最高位之前,称为定点小数,或者约定小数点固定在最低位之后,称为定点整数。定点小数是纯小数,定点整数是纯整数。
当数据小于定点数能表示的最小值时,计算机将它们作0处理,称为下溢;大于定点数能表示的最大值时,计算机将无法表示,称为上溢,上溢和下溢统称为溢出。
当然,小数点放在哪儿,这纯粹是一种约定。我们也可以约定小数点在中间的某个位,比如8位字长的机器,我们约定小数点在正中间,即我们可以将一个8位二进制数 xxxx xxxx 解读为:xxxx.xxxx。这种方法克服了“定点小数”和“定点整数”只能表示纯小数或纯整数的不足,可以表示一个既含整数部分,又含小数部分的数,但这种表示形式有诸多坏处,比如当要表示的数是一个纯小数且“很小”时,则这个数的大部分位都被0占据,浪费了资源,精度也不高,由此,我们引入了“浮点格式”,正如“科学计数法”所带来的好处那样,本来很大或很小的数都是要写的很长很长,现在可以用不多的几位数来表示那些很大或很小的数了,比如0.00000001可以写成0.1×2^(-7)。
浮点格式:
在机器中的一个浮点数包括尾数阶码两部分,尾数用纯小数形式(定点小数)表示,阶码用纯整数(定点整数)形式表示。尾数部分给出有效数字的位数,因而决定了浮点数的表示精度。阶码指明小数点在数据中的位置,因而决定了浮点数的表示范围。尾数和阶码各需要一个符号位。


在未统一约定的情况下,浮点数的表示形式不唯一。例如:11.01 也可以表示成 0.01101×2^3 或 0.1101×2^2 等等。
在两种情况下机器将浮点数视为0,称为机器零
1.不论阶码为何值,只要浮点数的尾数为0
2.无论尾数为何值,只要阶码的值比所能表示的最小值还要小
为了提高数据的表示精度,当尾数的值不为0时,其尾数域的最高有效位应为1,否则要进行“规格化”,即修改阶码同时移动小数点,使浮点数的形式改变,值保持不变。
IEEE754
IEEE754是目前最受认可流传最为广泛的浮点数标准。
该标准定义了两种格式(双精度和单精度)的浮点数。
该标准还定义了双精度和单精度浮点数的扩展格式(也称“中间格式”)。
扩展格式包括:
 
为阶码分配更多的位(扩展表示范围)
为尾数分配更多的位(扩展数的精度)
扩展格式在计算过程中被使用,由于其精度和范围被扩大了,所以能够达到比要求精度更高的精度,然后再对这个中间结果进行取舍,得到最终结果。这样能使计算过程中精度尽可能高。
单精度格式
长度为32位
1位符号位 | 8为阶码 | 23位尾数
双精度格式
长度为64位
1位符号位 | 11位阶码 | 52位尾数
注意事项:拿单精度格式来说,双精度格式以此类推
1)"符号位"表示的是数本身的正负,至于指数的正负,则在8位阶码里边已包含了。
2)阶码用移码表示
3)尾数用原码表示。
4)尾数要统一规格化成1.xxxxxx的格式,既然所有的尾数都是这个格式,那么前边的1就不用存入计算机了,只存储后边的xxxxx就行了。所以,虽然只给尾数分配了23位,但实际上表示的数是24位的。
看一个例子就明白了。
关于IEEE754的一个例子(2011年全国研究生入学计算机统考真题)
问题:
float型数通常用IEEE754单精度浮点数格式表示,若编译器将float型变量x分配在一个32位浮点寄存器R中,其中x=-8.25,请问R中的内容是什么?
解答:
将-8.25转换成2进制,为-1000.01B
将该数规格化,为 -1.00001×23
回想单精度的格式:1位符号位 | 8为阶码 | 23位尾数,依次填入符号位、阶码、尾数就好了。
显然符号位为1,表示负数。
阶为“3次方”,所以阶码为“3的移码”,先求出3的移码
IEEE754规定,单精度数的阶码偏置值为127,所以3的移码为127+3=130
所以阶码部分的8位应该是130这个十进制数的原码,即1000 0010
尾数为1.00001,去掉前边的1,就是00001, 所以尾数部分的23位就是: 0000 1000 0000 0000 0000 000
将这三部分拼接起来,得到最终R里边存放的内容为:1100 0001 0000 0100 0000 0000 0000 0000, 写成16进制为C1040000H
定点和浮点的对比
定点浮点各有优劣,定点运算快,但表示范围没有浮点大,精度没有浮点高。
一般来说,通用的大型机大多采用浮点数,或同时采用浮点、定点数。小型、微型机、控制机等一般采用定点数,当需要进行浮点运算时,可通过软件实现,也可以外加一个浮点协处理器来实现浮点运算。
 
注意,以下内容中,为了叙述方便我们约定,“机器字长为n+1位,1位表示负号,剩余n位表示数值”,凡是涉及到“取值范围”,“如何取模”等问题,其中的n的意义皆遵从这个约定。

真值和机器码
真值:平时手写出来的数,5、-3之类的,
机器码:真值在计算机里边的格式,将符号和数值一起编码。
机器数分为无符号数和有符号数。
无符号数:所有的位全部用来表示数本身
有符号数:机器数中的某些位用来表示数的符号,其他的位用来表示数值本身。
有符号数的整数的表示方式有四种:原码、反码、补码、移码
有符号数小数表示是尾数和阶码写在一起,其本质上还是整数。
原码和反码的0都有两种表示形式,正0和负0,所以原码和反码的表示范围都是一个关于0对称的闭区间。

原码:
写原码时注意写符号位,特别是正数,不要把符号位0给丢了
正数原码就是化成二进制后在前边加0
负数原码就是化成二进制后在前边加1
取值范围
纯小数时:
当符号位为0,数值位全为1时取到最大值:由等比数列求和公式知,最大值为2-1+2-2+…+2-n=1-2-n
当符号位为1,数值位全为1时取到最小值:同样地,最小值为2-n-1
纯整数时:
同样有等比数列求和公式知,取值范围为:-(2n-1)≤x≤2n-1
反码:
本身没啥用,就是由原码求补码的一种中间过渡产物。
保持原码符号位不变,其余各位取反
取值范围
和原码的取值范围完全一样,无非原码是符号位为0,其余位皆为1时取到最大值,而反码是符号位为1,其余位皆为0时取到最大值。形式不同,实质完全一样。
补码:
定义:
正数的补码就是它的原码
负数的补码是它的模减去它的绝对值,或说是它本身加上它的模
求补码的模:
给你一个补码形式的数,让你求它的模,就把符号位往前进一位,这一位的值就是它的模。
想象一下,一个n+1位字长的机器,1位符号位,n位数值位,当运算结果使得符号位产生向上一位的进位时,这个进位由于硬件的限制而自然被舍掉了,那么这被舍掉的一位的值,就是模。
纯小数的模为2,n位整数的模为2^(n+1)
补码的取值范围问题(以8位字长为例)
关于这个问题详情参考《另一个视角解读计算机编码-补码编码》,看唐朔飞组成原理P225下边那个表,应该更能明白所谓“在一个环上编码”。
 
先讨论纯整数。首先将0编码为0000 0000,然后将1编码为0000 0001,那么为了使-1+1=0成立,就应该把-1编码为1111 1111,而根据-2+1=-1,可知应该把-2编码为1111 1110,想象在一个环上,由0000 0000开始,往左是减小,往右是增大,往左走尽头是1000 0000,再减符号位就要变了,就要跨入环的另一半,进入正数的范围内了,这个1000 0000就是补码能够取到的最小值,其真值为-128。
这里我们并非通过“符号位写‘-’,剩余各位取反,末位加1”这种方法算出补码1000 0000所对应的真值为-128的
不信我们用这种方法来做一下,1000 0000的符号位写‘-’剩余各位为000 0000,取反之后为111 1111,加1之后变成000 0000,得到的真值是-0000000,最高位溢出了,这种算法在这里行不通。
我们之所以说补码1000 0000对应的真值是-128,那是因为从上边所述的“考察编码的角度”,由“将0编码成0000 0000”而一步步推演至全局,推演到-127时,将-127编码为1000 0001,而继续减小,就变成了-128,于是将-128编码为1000 0000。这里将1000 0000与-128对应起来,只是一种编码的方式,是一种强行规定的映射罢了,因为1000 0000是一个交界处,再往左走,就走到了0111 1111,进入了正半环了。在原码和反码的编码方式中,我们把交界处编码为0,即1000 0000和0000 0000 皆是0的编码,在补码中,我们觉得没必要将0编成两个不同的编码,所以就把在原码中赋予0的两个编码中的一个解放出来,放在负数的最左端了。然而须知这个最左端的数,并不能用“各位取反、末位加1”来算,而只能先算出它的邻居-127,然后再推一步得到-128。
求补码能取到的最大值是很容易的,正如原码最大值那样,取0111 1111就是最大值。
纯小数的补码也是一样。最小值为1000 0000,对应-1。最大值为0111 1111。
使用补码带来的好处:
1.使符号位能与有效值部分一起参加运算,从而简化运算规则
2.使减法运算转换为加法运算,简化计算机中运算器的线路设计
一些性质
两个互为补数的数,它们的绝对值之和等于模。
-1不属于小数的范围,但在小数的补码中,却有-1存在。
移码:
两种定义方式:
一:对于某一个系列或集合的数,把它们都映射到数轴的正半轴上去,使得所有的数都不为负数,并且这种映射保持他们在数轴上的相对位置不变,即若x的真值大于y的真值,则x的移码一定大于y的移码。这种映射的数学表示为:[x]=x+2.(这里的 [x]=x+2 并非硬性规定,而是一般的习惯,比如IEEE754就没有遵循这个习惯,IEEE754在单精度情况下就取的是x+127,在双精度情况下就取的是x+1023。要注意只有在取 [x]=x+2的情况下,“移码就是补码的符号位取反”这一规律才成立)。
二:移码就是将补码的符号位取反。
移码所带来的好处:
1.方便比较大小
由于所有的数在经过映射之后皆不为负且相对大小不变,所以可直接将移码当做无符号数,一眼看出两个数谁大谁小。若是用补码,则比较起大小就挺麻烦了。
2.使机器零为全0。
移码的最小值为全0,而“阶码小于机器所能表达的最小值(即阶码部分为全0)”是机器零的一种。
移码的一些性质
当移码的各位都为0时,该移码对应的数据是所有能够表示的数据中的最小值。当移码各位都是1时,是其所能表示的最大值
移码的用途
浮点数的阶码是用移码表示的。原因如下:
1.方便比较大小和对阶。
2.用移码来表示阶码的话可以提高表示数据的精度。
如果不采用移码来表示阶码,那么阶码就会出现负值,当需要把该数据转换成非阶码浮点数据时我们就需要对尾数进行左移(做乘法运算),这样的话最先移去的是尾数的高位,而高位的丢失是严重影响精确度的。若用移码表示阶码,则我们在转换时总是做右移操作,这样最先移去的是最低位,比较好地保持了数据的精度。
最后,四种编码的总结:
真值和补码的互推
由真值求补码:原码除符号位外,每位取反,末位加1
由补码求真值:将符号位写为负号“-”,其余各位按位取反,末位加1
注意,这两种互推法,按位取反的时候都是不带符号位的
注意:这种互推法很实用,但不适用于补码所能表示的最小的那个数,比如四位情况下,[-8]=1000,就不能用上述方法互推。
原码、反码、补码当x为正数时,是一样的
真正具有深刻内涵的实用价值的是补码,所以最好清楚补码的数学定义机器内涵,明白补码的“模”的作用,至于原码、反码的数学定义形式,什么 [x]=1-x 之类的,个人认为全是为了凑个形式完整,没有必要做详细了解,只要能做到给出一个x,会求出其原码和反码就行了。
应用场合:
原码:IEEE754 浮点数用原码表示尾码
反码:求补的过程中要先求反再加一,反码就是这个过程的中间产物
补码:运算时候用补码运算
移码:浮点数的阶码用移码表示
取值范围
原码和反码的取值范围相同
补码的取值范围在原码范围的基础上多往左(负方向)走了一位
移码的范围和补码一样。

posted on 2011-10-24 02:52  ybwang1989  阅读(6089)  评论(0编辑  收藏  举报

导航