原码为什么会出现?
首先要明确的是,计算机只知道0和1。
举个例子:
十进制数10在计算机内的存储形式为(以32位系统来说)
00000000 00000000 00000000 00001010
那么问题来了,-10在计算机内是如何存储的呢?
是在上面这个数前面加一个“-”号吗?(请记得计算机世界里只有0 和1)显然不是。
原码用最高位的的0表示正数,1表示负数。所以-10表示为
10000000 00000000 00000000 00001010
上面解决了数存储的问题,但算数运算方面的问题呢?
10 + (-10) = 0这点毫无疑问。但你如果用上面10和-10的二进制数进行运算:
00000000 00000000 00000000 00001010 +10000000 00000000 00000000 00001010=10000000 00000000 00000000 00010100
显然不为零。
那如何解决这个问题呢??
反码为什么会出现?
反码的诞生正是为了解决算数运算问题。
反码在原码的基础上对负数做了相应的改进,保留了正数在计算机内的存储形式即以原码存储。但负数则根据该数的正数形式进行各位取反(除最高位符号位),1变0,0变1,顾称之为反码。(这将在一定程度上解决正负数运算问题,其中用了模运算的思想)
-10的存储由原来的 10000000 00000000 00000000 00001010变为11111111 11111111 11111111 11110101
反码的出现简单解决了正负数相加的问题。(为什么说“简单”呢?因为反码的出现解决了一部分正负数相加的问题)
我们再来计算一下10 + (-10)
00000000 00000000 00000000 00001010 + 11111111 11111111 11111111 11110101 = 11111111 11111111 11111111 11111111
这里的结果正是 -0 在计算机内的存储形式。
新的问题出现了,0在计算机内有两个存储形式
+0 00000000 00000000 00000000 00000000
-0 11111111 11111111 11111111 11111111
+0的存储没有什么问题,但-0这个现象就明显存在问题,在数学中,0是个相对来说比较特殊的数是唯一一个正负数相同的数。换句话说,+0,-0只能存储一个,为了更符合人们的习惯,选择了+0。
这里就出现一个新的问题,-0的这个位置是存在的,而且10+(-10)= -0,怎么解决呢?
补码为什么会出现?
补码的出现正是为了解决上一个问题。
补码是在反码的基础上进一步改进的,补码也保留了正数的二进制原码,未作改动,对于负数则是在其反码的基础上+1
10的补码 00000000 00000000 00000000 00001010
-10的补码11111111 11111111 11111111 11110110
我们可以再试一试10 +(-10)
00000000 00000000 00000000 00001010 + 11111111 11111111 11111111 11110110 = 00000000 00000000 00000000 00000000
至此,在原码->反码->补码改进过程中,成功解决了数的存储和算数运算问题,成为计算机内的最优选择。这也是为什么对于有符号数,负数的存储个数总是要比正数多一个的原因,-0的位置会多存储一个负数。
补充:
至于补码为什么会选择取反加1操作,下面这篇博客提供了解释。