一、概念清单
-
机器数
-
真值
-
原码
-
反码
-
补码
二、概念详解
1. 机器数
-
机器数是一个数在计算机中的二进制表示形式。
-
机器数带符号,最高位存放,正数为0,负数为1。
十进制数+3,计算机字长为8位的话,转换二进制为00000011 十进制数-3,计算机字长为8位的话,转换二进制为10000011 上述这两个二进制就是机器数。
2. 真值
-
由于符号位的存在,机器数不等于真值。
-
带符号的机器数,真正的数值。
-3是真值,它的机器数是10000011(其形式值为131(十进制))
3. 原码
-
原码是符号位加上真值的绝对值,即第一位为符号位,其余位表示值。
十进制数+1原码为 00000001 十进制数-1原码为 10000001
-
因为第一位是符号位,所以8位二进制的取值范围为:
[11111111,01111111]
即
[-127,127]
-
原码是人脑最容易理解和计算的编码方式。
-
无符号数用原码。
4. 反码
-
正数的反码是其本身。
-
负数的反码是其原码基础上,符号位不变,其余各位取反。
[+1] = [00000001]【原】 = [00000001]【反】 [-1] = [10000001]【原】 = [11111110]【反】
-
反码不容易被人脑直接看出真值,通常需要转换成原码
5. 补码
-
正数的补码是其本身。
-
负数的补码是其原码的基础上,符号位不变,其余各位取反,最后+1。
[+1] = [00000001]【原】 = [00000001]【反】 = [00000001]【补】 [-1] = [10000001]【原】 = [11111110]【反】 = [11111111]【补】
-
补码不容易被人脑直接看出真值,通常需要转换成原码
-
计算机中,有符号数采用补码
三、有符号数采用补码的意义与方法
-
意义:为了让符号位参与运算,以简化基础电路设计。
人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减. (真值的概念在本文最开头). 但是对于计算机, 加减乘数已经是最基础的运算, 要设计的尽量简单. 计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了,于是人们开始探索 将符号位参与运算, 并且只保留加法的方法.
-
方法:
举例来说:限定为8位二进制,计算十进制的表达式:1-1=0
-
若机器码采用原码来计算,会是这样的结果:
1-1 = 1 + (-1)= [0000 0001]【原】+[1000 0001]【原】= [1000 0010]【原】= -2【十进制】 //明显错误
-
若机器码采用反码来计算,会是这样的结果:
1-1 = 1 + (-1)= [0000 0001]【原】+[1000 0001]【原】= [0000 0001]【反】+[1111 1110]【反】= [1111 1111]【反】= [1000 0000]【原】= -0 【十进制】 //明显错误,0应该是唯一的,不能让[0000 0000]【+0】[1000 0000]【-0】都来表示0.
-
若机器码采用补码来计算,会是这样的结果:
1-1 = 1 + (-1)= [0000 0001]【原】+[1000 0001]【原】= [0000 0001]【反】+[1111 1110]【反】= [0000 0001]【补】+[1111 1111]【补】= [0000 0000]【补】= [0000 0000]【原】= 0 【十进制】 //这样保证了0的唯一性。 还有一个额外的好处,若用原码、反码,取值范围都只限与[-127,127],但用补码是[-128,127]能多表示一个数-128。 (-1)+(-127)= [1000 0001]【原】+[1111 1111]【原】= [1111 1110]【反】+ [1000 0000]【反】= [1111 1111]【补】+[1000 0001]【补】= [1000 0000]【补】 //注意:-128在限定为8位时没有原码和反码,不信?那你将[1000 0000]【补】往原码进行转换,会得出[0000 0000]【原】,这明显错误! 若机器采用补码表示有符号数,对于编程中常用32位的int类型,表数范围可以是[-2<sup>31</sup> , 2<sup>31</sup>-1],而不是原码的表数范围[-2<sup>31</sup>-1 , 2<sup>31</sup>-1]
-
四、如何将二进制补码还原为原码?
-
方法一:我们可以按原路返回,就是将计算机中存储的二进制补码减1,然后取反,再得到原码,换成相应负数即可,不过这样有点麻烦,因为涉及到了减法操作。
-
方法二:将负数的补码先取反,然后加1,最高位置换为1即可。
对于-10,在计算机中存储为
11111111 11111111 11111111 11110110 【补码形式】
先取反,得
00000000 00000000 00000000 00001001
再加1,得
00000000 00000000 00000000 00001010
最高位变1,即
10000000 00000000 00000000 00001010 【原码形式】
结果是“-10”
五、奇技淫巧
1. 取反的快捷算法
~x等同于-(x+1)
10进制数2016,转32位2进制数为:
0000 0111 1110 0000
~按位取反:
1111 1000 0001 1111 【对应十进制数:-2017】
结果为:
(~2016) = -2017
六、参考资料
-
原码, 反码, 补码 详解 【这个大神太NB,把数学知识扯进来了,我有些看不明白,暂未将内容加入本文,后续看明白了补充进来】