今天看到原码,反码和补码,突然发现还是有点云里雾里,就重新复习了一下。
在计算机内部,所有信息都是用二进制数串的形式表示的整数。是整数就有正负之分,而这个正负也需要用二进制来表示,所以一般会用最高有效位作为符号位,0表示正号、1表示负号。这种正负号数字化的机内表示形式就称为“机器数”,而相应的机器外部用正负号表示的数称为“真值”,将一个真值表示成二进制字串的机器数的过程就称为编码。
带符号整数有原码、反码、补码、移码等几种编码方式:
1) 原码的特点就是编码简单直观,与真值转换非常方便。
2) 反码很少会被用到,他主要的用途就是作为原码与补码的一个桥梁。
3) 补码和原码是互补的关系,补码和原码同余,即互为补码。就是说补码和原码的数值位相加,刚好能使数值位全为0并且进1。【这里引入另一个概念——模数,模数从屋里意义上讲是某种计量器的容量。这里我们经常举的一个例子就是钟表,其模数为12,即每到12就重新从0开始。数学上叫取模或求余(mod),一般的程序语言用%表示求余操作。】
4) 移码,又叫增码,是符号位取反的补码,一般用做浮点数的阶码,引入的目的是为了保证浮点数的机器零为全0。
他们之间的转换如下:
十进制 |
43 |
-43 |
二进制 |
101011 |
-101011 |
原码 |
00101011 |
10101011 |
反码 |
00101011 |
11010100 |
补码 |
00101011 |
11010101 |
移码 |
10101011 |
01010101 |
如上表所示,X真值十进制表示为43,二进制表示为101011,-X为-43和-101011。
l 当X真值为正时,原码、反码、补码完全相同;
l 当X真值为负时,反码的符号位不变,其他各位取反;补码则是反码加1;
l 移码不管正负,只要将补码的符号位取反即可。
在计算机中,数据是以补码的形式存储的。那为什么不用原码和反码呢?
对于一个8字节的整数(int)来说,范围是2的8次方,表示-128~127。如下面的表格所示,如果用原码和反码,+0和-0是同一个数却有两个不同的表示,这样不仅会使计算机多一层处理,还会浪费一个表示范围;而补码就能很好的解决这个问题。(-128只有补码,而没有原码和反码,因为数值位只能表示0~127。)
|
编码 |
真值 |
编码 |
真值 |
|
原码 |
00000000 |
0 |
10000000 |
-0 |
|
00000001 |
1 |
10000001 |
-1 |
|
|
00000010 |
2 |
10000010 |
-2 |
|
|
01111111 |
127 |
11111111 |
-127 |
|
|
反码 |
00000000 |
0 |
11111111 |
-0 |
|
00000001 |
1 |
11111110 |
-1 |
|
|
00000010 |
2 |
11111101 |
-2 |
|
|
01111111 |
127 |
10000000 |
-127 |
|
|
补码 |
00000000 |
0 |
00000000 |
-0 |
11111111 + 1 |
00000001 |
1 |
11111111 |
-1 |
11111110 + 1 |
|
00000010 |
2 |
11111110 |
-2 |
11111101 + 1 |
|
01111111 |
127 |
10000001 |
-127 |
10000000 + 1 |
|
|
|
10000000 |
-128 |
|
除了表示范围更全以外,补码还有很多特性,能给符号运算带来便利,如下: 【其中最有名的就是补码能把减法转化成加法,提高CPU的效率】
[X]补,表示X的补码;|X|,表示X的绝对值。
当X < 0 时[X]补 = 28 - |X|;
当X >=0 时[X]补 = |X| =X;
[X+Y]补 = [X]补 + [Y]补;
[X-Y]补 = [X]补 - [Y]补 = [X]补 + [-Y]补;
[X*Y]补= [X]补 * [Y]补 (两真数相乘的补码等于补码的相乘)
正数的补码取反加1后,为其对应的负数的补码;负数的补码取反加1后为其绝对值的补码。
参考博文:http://www.toceansoft.com/relevance/4316.jhtml
原文地址:http://blog.csdn.net/tiwerbao/article/details/43995335