对于程序猿或者是其它搞计算机类的人员,这篇只是为了解释一下原码,反码,补码之间的计算和解释上一篇的a + ~a = -1的问题!!!
首先先介绍一下整数在计算机中表示方法,数在计算机中都是用二进制表示,但是字节长度就不一定了,不同的机器可能就不一样
而且在计算机系统中,补码是最重要的编码,数值一律用补码来表示和存储
移码(又叫增码)是符号位取反的补码,一般用做浮点数的阶码,引入的目的是为了保证浮点数的机器零为全0
整数有正,有负的,所以计算机中为了表示正负,用字节的最高位来表示正负,其它位表示数值
例如大多数计算机体系中,(signed) int 就是一个有符号的数,占4个字节,signed可以不写,默认int就是signed int,另外signed默认也是signed int,不过这样写不规范,不建议这么写,
为了方便演示,下面就以一个字节为例!
正数的最高位是0,负数的最高位是1
正数原码和反码,补码都是一样的,都是正数本身
对于负数
原码是符号位为1,其它位和数本身的正数一样,也就是负数的原码等于其相反数的原码,但是最高位为1即可
反码就是在负数的原码基础上,符号位不变,其余的按位取反
补码就是在负数的反码基础上,符号位不变,加上1即可
4. 从十进制求它二进制的原码,反码,补码就按上面的方法,但是知道一个补码怎么求数本身呢,对于正数不用求,因为就等于其本身(看符号位是否为0),但是对于符号位为1的补码,那就要再求一次补码了,过程是一样的,符号位不变,按位取反,最后加上1即可!然后算出其10进制的数的值再加上负号即可。下面举例子来说明一下!!!
eg:
7(10)-->0000 0111(2) 最高位0表示符号位,0表示正数
原码=反码=补码=0000 0111
-7(10)
原码:1000 0111(2) 最高位1表示为负数
反码:1111 1000(2) 在原码基础上符号位不变,其它的按位取反
补码:1111 1001(2) 在反码基础上符号位不变,再加上1
note:对于已经比较熟悉这些转换的人来说,就是~|-7|+1 即可!这个不作解释
已知补码求数本身---->1111 1011(2)-->?
note:方法就是再求一次其补码即可
1111 1011-->1000 0100 符号位不变,其它的按位取反
1000 0100-->1000 0101 符号位不变,再加上1 --> -5(10)
好了现在可以回答上一篇《嵌入式c语言中的位运算》的问题了,假如是一个正数a的~a那么就是其它相反数的补码,但是没有加上1,所以比相反数少1(~a ==-a-1),所以和相反数-1相加就于-1,例如: a = 5, ~a + a =a+(-a -1) = -1 了!现在假如是一个负数,a = -5 1111 1011[补码](计算机中用补码表示整数) 把补码按位取反之后(包括符号位)为 0000 0100 正常情况下是符号位不变而且还要加上1的,但是这里没有加上1和保持符号位不变,所以就变成数本身的相反数-1了,也就是~a == -a-1,所以a+~a = a+(-a-1) = -1
下面用程序来证明吧!
1 #include <stdio.h> 2 int main() 3 { 4 int a = 5; 5 int b = ~a; 6 int ret = a+b; 7 printf("%d + %d = %d \n",a,b,ret); 8 9 a = -22; 10 b = ~a; 11 ret = a + b; 12 printf("%d + %d = %d \n",a,b,ret); 13 }
本文出自 “挑战自己” 博客,请务必保留此出处http://lovechocolate.blog.51cto.com/6757953/1569372
原文地址:http://lovechocolate.blog.51cto.com/6757953/1569372