补码表示的引入是基于模的概念。所谓模是指一个计数器的容量。比如钟表以12为一个计数循环,即可看做以12为模。在进行钟表对时时,假设当前钟表的时针停在九点位置,要将时针拨到2点,可以采用两种方法。一种是顺时针拨动指针向前5个小时,9+5=14,14-12=2,指针指向2点。这是因为钟表上只有12个刻度,即钟表的计数容量是12,当指针超过12点的时候钟表要重新从0点开始计时;另一种方法是逆时针转动7个小时,9-7=2,指针同样也指向2点。
数学上取模的符号是mod,在对于采用12为模的钟表而言,9-7=(9+5)mod12,称为在模12条件下9-7等于9+7。7加5等于模12,这样的数我们称它们互为补数,即对于模12而言7是5的补数,同样5也是7的补数。由上面的计算我们可以知道对于一个确定的模而言,当需要减去一个数x时,可以用加上x对应的负数-x的补数来代替。我们还可以知道如何求补码:整数的补码等于其本身;负数的补码等于模与该数的绝对值之差。
钟表记小时数的容量是12,钟表的模就是12,那计算机中计数器的容量是多少哪?在计算机中,由于硬件的运算器与寄存器都有一定的字长限制,即计算机硬件能够一次处理的二进制数据的长度是有限的,因此计算机中的运算也是有模运算的。以位数为8的二进制计数器为例,计数的范围是00000000~11111111,当计数器的数值记到,11111111时,再加1,计数器达到100000000,产生溢出,最高位1被丢掉,使得计数器又从00000000开始计数。对于这个8位二进制计数器而言,产生溢出的量100000000就是计数器的模,相当与前面钟表示例中的12。
对于使用n位二进制数表示数据的硬件,纯小数的具有x1.x2x3……xn-1xn的形式,xn代表的是一个数位,它能表示的范围是0.0000……00~1.1111……11,溢出的值是10.0000......00,它的模是2;纯整数具有x1x2x3……xn-1xn的形式,能表示的范围是0000……00~1111……11,溢出的值是10000……00,它的模就是2^n。下面按照纯小数、纯整数分别给出补码的定义。
纯小数x:0<=x<1,补码是其自身;-1<=x<0,补码等于2+x。
纯整数x:0<=x<2^(n-1),补码是其自身;-2^(n-1)<=x<0,补码等于2^n+x。
Java语言中的整数系列都可以采用补码表示。
例3-1:求一下各数的补码(8位二进制),+0.1010110、-0.1010110、+1010110、-1010110。
结果:0.1010110、1.0101010、01010110、10101010。
例3-2:几个特殊数的补码:
ü 真值0
由补码定义,如下:
纯小数:+0补码=0.000…0 (n个0)
-0补码=2-0.000…0=0.000…0
纯整数:+0补码=0000…0 (n个0)
-0补码=2^n-1-0000…0=0000…0
在补码中真值0的表示是唯一的。
ü 真值-1
由补码定义,如下:
纯小数:-1补码=2-1.000…0=1.000…0 (符号位一个1,数值位上n-1个0)
纯整数:-1补码=2^n-0000…1=1111…1 (n个1)
在纯小数的原码当中,-1是无法表示的;而在补码中,纯小数的补码最小值可以表示到-1。比较直观的理解是符号位的1既表示符号也表示数值1。
ü 真值-2^(n-1)
[-2^(n-1)]补码=2^n-2^(n-1)=1000…0 (符号位一个1,数值位上n-1个0)
在纯整数的原码当中,-2^(n-1)是无法被表示的,而在补码当中,在模-2^n的条件下,纯整数的补码最小可以表示到-2^(n-1)。比较直观的理解是符号位的1既可以表示符号1,也表示数值2^(n-1)。
例3-3:补码的简便求法,若x>=0,则x的补码为其自身,并使符号位为0;若x<0,则将x的各位取反,然后在最低位上加1,并使符号位为1,既得到x的补码。
证明:对于x>=0,根据补码的定义可得;
当x<0的时候,有两种情况:x为纯小数、x为纯整数。
当x为纯小数的时候,[x]补码=2+[x]原码=10.00…0(一个1,n个0)-0.x1x2…xn-1
稍稍做一点变化,原式=1.11…1(n个1)+0.00…1(n-1个0,最低位一个1)-0.x1x2…xn-1
=(1.11…1-0.x1x2…xn-1)+0.00…1
1.11…1-0.x1x2…xn-1等于将x的各位按位取反,再加上0.00…1,等于在最低位上加1。同样的方法,我们也可以证明当x为纯整数的的时候,结论也成立。
综上,得证。
补码与减法运算
前面在介绍模的时候已经提到:对某一个确定的模而言,当需要减去一个数x的时候,可以用加上对应的负数的补码来代替。既,X-Y等价于X+[Y]补码。因此需要在已知Y的条件下求[-Y]补码。如果Y已经是补码了,那么如何求-Y的补码哪?如果先将Y转化成原码,再求(-(Y原码))的补码,这样求得结果肯定没有问题,但是很累。有没有简便的算法哪。看下面的讨论。
设真值X>0
X-X=0 à 减去一个数等于加上它的补码,因此有 [X]补码+[-X]补码 = 0 = 模 à [-X]补码=模-[X]补码=[[X]补码]补码=对X的补码求补码。
由上面的讨论我们可以得出对补码相反数求补的简单规则是:将X的各位(含符号位)取反,然后在最低位上加1,既得到[-X]补码(既,取补码的补码)。
例3-4:已知X,求-X的补码。
ü X=01001101 -X补码=10110011
ü X=10110010 -X补码=01001110
数学上取模的符号是mod,在对于采用12为模的钟表而言,9-7=(9+5)mod12,称为在模12条件下9-7等于9+7。7加5等于模12,这样的数我们称它们互为补数,即对于模12而言7是5的补数,同样5也是7的补数。由上面的计算我们可以知道对于一个确定的模而言,当需要减去一个数x时,可以用加上x对应的负数-x的补数来代替。我们还可以知道如何求补码:整数的补码等于其本身;负数的补码等于模与该数的绝对值之差。
钟表记小时数的容量是12,钟表的模就是12,那计算机中计数器的容量是多少哪?在计算机中,由于硬件的运算器与寄存器都有一定的字长限制,即计算机硬件能够一次处理的二进制数据的长度是有限的,因此计算机中的运算也是有模运算的。以位数为8的二进制计数器为例,计数的范围是00000000~11111111,当计数器的数值记到,11111111时,再加1,计数器达到100000000,产生溢出,最高位1被丢掉,使得计数器又从00000000开始计数。对于这个8位二进制计数器而言,产生溢出的量100000000就是计数器的模,相当与前面钟表示例中的12。
对于使用n位二进制数表示数据的硬件,纯小数的具有x1.x2x3……xn-1xn的形式,xn代表的是一个数位,它能表示的范围是0.0000……00~1.1111……11,溢出的值是10.0000......00,它的模是2;纯整数具有x1x2x3……xn-1xn的形式,能表示的范围是0000……00~1111……11,溢出的值是10000……00,它的模就是2^n。下面按照纯小数、纯整数分别给出补码的定义。
纯小数x:0<=x<1,补码是其自身;-1<=x<0,补码等于2+x。
纯整数x:0<=x<2^(n-1),补码是其自身;-2^(n-1)<=x<0,补码等于2^n+x。
Java语言中的整数系列都可以采用补码表示。
例3-1:求一下各数的补码(8位二进制),+0.1010110、-0.1010110、+1010110、-1010110。
结果:0.1010110、1.0101010、01010110、10101010。
例3-2:几个特殊数的补码:
ü 真值0
由补码定义,如下:
纯小数:+0补码=0.000…0 (n个0)
-0补码=2-0.000…0=0.000…0
纯整数:+0补码=0000…0 (n个0)
-0补码=2^n-1-0000…0=0000…0
在补码中真值0的表示是唯一的。
ü 真值-1
由补码定义,如下:
纯小数:-1补码=2-1.000…0=1.000…0 (符号位一个1,数值位上n-1个0)
纯整数:-1补码=2^n-0000…1=1111…1 (n个1)
在纯小数的原码当中,-1是无法表示的;而在补码中,纯小数的补码最小值可以表示到-1。比较直观的理解是符号位的1既表示符号也表示数值1。
ü 真值-2^(n-1)
[-2^(n-1)]补码=2^n-2^(n-1)=1000…0 (符号位一个1,数值位上n-1个0)
在纯整数的原码当中,-2^(n-1)是无法被表示的,而在补码当中,在模-2^n的条件下,纯整数的补码最小可以表示到-2^(n-1)。比较直观的理解是符号位的1既可以表示符号1,也表示数值2^(n-1)。
例3-3:补码的简便求法,若x>=0,则x的补码为其自身,并使符号位为0;若x<0,则将x的各位取反,然后在最低位上加1,并使符号位为1,既得到x的补码。
证明:对于x>=0,根据补码的定义可得;
当x<0的时候,有两种情况:x为纯小数、x为纯整数。
当x为纯小数的时候,[x]补码=2+[x]原码=10.00…0(一个1,n个0)-0.x1x2…xn-1
稍稍做一点变化,原式=1.11…1(n个1)+0.00…1(n-1个0,最低位一个1)-0.x1x2…xn-1
=(1.11…1-0.x1x2…xn-1)+0.00…1
1.11…1-0.x1x2…xn-1等于将x的各位按位取反,再加上0.00…1,等于在最低位上加1。同样的方法,我们也可以证明当x为纯整数的的时候,结论也成立。
综上,得证。
补码与减法运算
前面在介绍模的时候已经提到:对某一个确定的模而言,当需要减去一个数x的时候,可以用加上对应的负数的补码来代替。既,X-Y等价于X+[Y]补码。因此需要在已知Y的条件下求[-Y]补码。如果Y已经是补码了,那么如何求-Y的补码哪?如果先将Y转化成原码,再求(-(Y原码))的补码,这样求得结果肯定没有问题,但是很累。有没有简便的算法哪。看下面的讨论。
设真值X>0
X-X=0 à 减去一个数等于加上它的补码,因此有 [X]补码+[-X]补码 = 0 = 模 à [-X]补码=模-[X]补码=[[X]补码]补码=对X的补码求补码。
由上面的讨论我们可以得出对补码相反数求补的简单规则是:将X的各位(含符号位)取反,然后在最低位上加1,既得到[-X]补码(既,取补码的补码)。
例3-4:已知X,求-X的补码。
ü X=01001101 -X补码=10110011
ü X=10110010 -X补码=01001110