用户操作
[即时聊天] [发私信] [加为好友]
JohnID:dynamic516
42957次访问,排名2772(1),好友0人,关注者0人。
dynamic516的文章
原创 5 篇
翻译 0 篇
转载 0 篇
评论 0 篇
最近评论
文章分类
收藏
    相册
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 给定数据类型的补码表示,不能简单的用取反加一的方法来求反码的,介绍下2的补码系统收藏

    新一篇: linux学习使用总结-linux系统的安装和与windows双系统共享,linux常用的基本命令,今天贴在这里和大家分享 | 


    首先声明常用的几点,想了解更多详细内容读完全文(包括二进制补码系统的简单介绍):

    1,

    表示一个数值要先说明是用多少bit,例如:
    用8bit表示数值时,(-128)没有相对应的原码和反码, (-128)补码 = (1000  0000) 
    同理(2B=16bit)表示:(-32768)补码=(1000  0000  0000  0000),后面回给出证明,
    因为它是不能简单的用取反加一的方法来求反码的。

    2,

    证明:用(2B=16bit)表示:(-32768)补码=(1000  0000  0000  0000)

    (1)32767(正数补码与原码相同)是0111  1111  1111  1111
    (2)-1的补码,其原码取反在加一得 1111  1111  1111  1111
    (3)0111 1111 1111 1111+1000  0000  0000  0000=1111 1111 1111 1111
    (4)(令上式x==1000  0000  0000  0000)即:32767+x=-1
    (5)x=-32768


    至于用(2B=16bit)表示,取反加一求(-32768)的补码,还望哪个高手指点简单的证明过程。
    希望大家以后在被问为什么(-128)补码 = (1000  0000),
    (-32768)补码=(1000  0000  0000  0000)不要在说什么取反加一的话,
    那样你证明我看看。给出证明,免得人家不明白还以为你在谈什么高深的话题,
    结果却是被忽悠了。

    3,

    下面举例说明求负数的补码的补码

    -1的补码是0xFFFF. 它是这样求的:

    -1的原码:        1000  0000  0000  0001 ,
    数值位按位求反:       0xFFFE==1111 1111 1111 1110,
    末位加1:           0xFFFF==1111 1111 1111 1111

    现在还按这个补码的求法, 作用在0xFFFF上,
    0xFFFF  :          1111 1111 1111 1111
    数值位按位求反:       1000  0000  0000  0000
    末位加1:           1000 0000 0000 0001,

    这样又得到了-1。

    就像求负数的绝对值,彼此导来导去都可以。

    ***************************************************************************

    ***************************************************************************

    补码的计算和引进补码的原因:

    数值有正负之分,计算机就用一个数的最高位存放符号(0为正,1为负).
    这就是机器数的原码了.假设机器能处理的位数为8.即字长为1byte,
    原码能表示数值的范围为(-127~-0 +0~127)共256个.
    有了数值的表示方法就可以对数进行算术运算.
    但是很快就发现用带符号位的原码进行乘除运算时结果正确,
    而在加减运算的时候就出现了问题,如下: 假设字长为8bits

    ( 1 ) 10-  ( 1 )10 =  ( 1 )10 + ( -1 )10 =  ( 0 )10

    (00000001)原 + (10000001)原 = (10000010)原 = ( -2 ) 显然不正确.

    因为在两个整数的加法运算中是没有问题的,于是就发现问题出现在带符号位的负数身上,
    对除符号位外的其余各位逐位取反就产生了反码.反码的取值空间和原码相同且一一对应. 
    下面是反码的减法运算:

    ( 1 )10 -  ( 1 ) 10=  ( 1 ) 10+ ( -1 ) 10=  ( 0 )10

    (00000001) 反+ (11111110)反 =  (11111111)反 =  ( -0 )  有问题.

    ( 1 )10 -  ( 2)10 =  ( 1 )10 + ( -2 )10 =  ( -1 )10

    (00000001) 反+ (11111101)反 =  (11111110)反 =  ( -1 ) 正确

    问题出现在(+0)和(-0)上,在人们的计算概念中零是没有正负之分的.




    于是就引入了补码概念. 负数的补码就是对反码加一,而正数不变,正数的原码反码补码是一样的.
    在补码中用(-128)代替了(-0),所以补码的表示范围为:(-128~0~127)共256个.已知某数的补码,
    先求某数的反码,然后在对反码+1,就得到某数的原码.比如:
    已知某个数的补码是:10100110
    先对10100110求反,得:11011001
    再对11011001加1,得: 11011010
    那么这个数为-86

    原码表示的范围为:-(2^(n-1)-1)~+(2^(n-1)-1),
    反码表示的范围为与原码一样.
    补码表示的范围为:-2^(n-1)~+(2^(n-1)-1),
    其中n为机器字长。

    注意:
    0的补码是唯一的,为0000,0000    [+0]补=[-0]补=0000,0000    -0的反码为1111,1111
    8bit表示数值时(-128)没有相对应的原码和反码, (-128) = (10000000)  

    补码的加减运算如下:
    ( 1 ) 10-  ( 1 ) 10=  ( 1 )10 + ( -1 )10 =  ( 0 )10

    (00000001)补 + (11111111)补 =  (00000000)补 = ( 0 ) 正确

    ( 1 ) 10-  ( 2) 10=  ( 1 )10 + ( -2 )10 =  ( -1 )10

    (00000001) 补+ (11111110) 补=  (11111111)补 = ( -1 )  正确

    所以补码的设计目的是:

    ⑴使符号位能与有效值部分一起参加运算,从而简化计算机的运算规则.

    ⑵使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计

    所有这些转换都是在计算机的最底层进行的,而在我们使用的汇编、C等其他高级语言中使用的都是原码。
    看了上面这些大家应该对原码、反码、补码的知识印象更深了吧!!

    **************************************************************************

    **************************************************************************

    下面介绍2的补码记数法


    图1显示了两个完整的2的补码系统:一个是基于长度为3的位模式,
    另一个是基于长度为4的位模式。
    这种系统的构造方法是:从相应长度的0的串(例子中用3位和4位)开始,
    用二进制记数的方式一直记数到位模式是由一个0后面跟随尽可达到的数目1组成(列中是011和0111)为止。
    这些位模式表示值0,1,3,…。表示负数的位模式是通过从相应长度的1的串开始,然后用二进制倒记数的方式记数,
    一直到位模式是由一个1和随后尽可能达到的数目0所组成为止。
    这些位模式表示值-1,-2,-3,…。
    如果这种倒记数的方法使用时太困难,也可以从表最底部的位模式开始,
    向上记数。即从由一个1和随后尽可能达到的个数0组成的位模式开始一直到全
    由1组成的位模式为止。

    图一贴图01



    注意:在2的补码系统中,一个位模式最左边的位指示被表示数值的符号。因此,最左边的位被称为符号位。
    负值是用符号位为1的位模式来表示,非负值是由符号位为0的位模式来表示。
        在2的补码系统中,表示相同幅度的正负值的模式之间存在着简便的关系。从右至左读位模式,直到包括第一个1时,
    它们是等同的。继续读位模式,则相互之间就互补了(一个模式的补是由模式中的所有的0变为1、所有的1变为0而得到,
    0110和1001是互补的)。例如,图1的4位长模式中表示2和-2的模式都是以10结束,但是表示2的模式是以00开始,
    而表示-2的模式以11开始。这个观察引出了表示相同幅度的正值和负值的位模式之间进行相互转换的一个算法,
    即对原位模式从右向左逐位拷贝直到有一个1被拷贝为止,然后对原位模式中余下来的部分求补,把求补结果做拷贝,如图2所示。

    图2贴图1

    在熟悉了2的补码系统的这些特性基础上便可引出对2的补码表示形式解码的算法。如果待解码的位模式有为0的符号位,
    该位模式就好像是二进制表示形式,只需直接读出它的值。例如,0110表示值6,因为0110是6的二进制表示形式。
    如果待解码的位模式符号位为1,则表示是个负值,并且所有余下的部分表示数值的大小。其做法是:从右向左拷贝原位模式,
    直到有一个1被拷贝为止,然后对原位模式中余下来的部分求补,最后把所得到的模式当做是二进制表示形式进行解码。
    例如,解码模式1010,因为符号位为1,则表示的是个负值。因此,将这个模式转换为0110,此模式代表6,从而得出原来的模式表示-6。
    (2) 2的补码记数法中的加法
    要加由2的补码记数法表示的数值,除了所有的位模式包括答案在内,都运用了与二进制加法相同的算法。
    这就意味着在2的补码系统中进行加法时,最后的进位在答案的左端产生的附加位一定要舍去。于是,加0101和0010得0111;
    加0111和1011结果是0010(0111+1011=10010,舍去最左边的1,结果为0010,长度保持4位)。根据这种理解,
    考察图3中的三个加法问题。在每一种情况中,已经把问题转换成2的补码记数法(使用4位长的位模式),执行前面描述的加法过程,
    并且将结果解码返回到常用的基数10的记数法。

    贴图3贴图3

    采用2的补码记数法的机器需要知道的只是如何去加和求反就够了。例如,减法问题7-5与加法问题7+(-5)是相同的。
    因此,如果机器被请求从7(存储为0111)中减5(存储为0101),它首先将5改变为-5(表示为1011),
    然后执行0111+1011的加法过程取得0010,它表示2。

    发表于 @ 2006年04月21日 22:54:00|评论(loading...)|编辑

    新一篇: linux学习使用总结-linux系统的安装和与windows双系统共享,linux常用的基本命令,今天贴在这里和大家分享 | 

    评论:没有评论。

    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © John