目录
什么是原码、反码和补码?
在计算机中,我们通常用二进制来表示整数,因为二进制的每一位只有两个状态,可以用电路的开关来实现,方便计算机的存储和运算. 但是,二进制有一个问题,就是如何表示负数. 为了解决这个问题,人们提出了原码、反码和补码的概念.
原码:
原码是最直观的表示方法,对于有符号数来说,就是用二进制的最高位表示符号,0表示正数,1表示负数,其余位表示数值的绝对值.
有符号数
例如,8位有符号二进制的原码表示如下:
// 十进制 二进制原码
// +7 0000 0111
// -7 1000 0111
(PS:8位二进制数中间加个空格是为了方便观察,下面不再强调)
无符号数
如果表示的是无符号数,则将符号位(最高位)也用来表示数值的绝对值.同样的二进制数在表示有符号数时值是-7,表示无符号数时值为135(128+7).
同样的二进制数表示有符号数和无符号数的对比如下:
// 十进制 二进制原码
// 有符号数 -7 1000 0111
// 无符号数 135 1000 0111
无符号数没有补码,原码和反码的概念。因为无符号数只能表示非负整数,所以它们的原码、反码、补码都是相同的,即它们的原码、反码、补码都是它们的二进制表示。故下面不再对无符号数作过多赘述.
反码:
反码是对原码的符号位不变,其余位按位取反得到的结果.
例如,8位二进制的反码表示如下:
// 十进制 二进制原码 二进制反码
// +7 0000 0111 0000 0111
// -7 1000 0111 1111 1000
补码:
补码是对反码的末位加1得到的结果.
例如,8位二进制的补码表示如下:
// 十进制 二进制原码 二进制反码 二进制补码
// +7 0000 0111 0000 0111 0000 0111
// -7 1000 0111 1111 1000 1111 1001
为什么要用原码、反码和补码?
原码、反码和补码的作用主要是为了方便计算机进行整数的加减运算. 我们知道,计算机的运算器只能进行加法运算,减法运算要通过加法运算来实现. 例如,要计算A-B,就要转换为A+(-B)的形式.
因此,我们需要一种方法来表示负数,使得加法运算可以正确地处理正数和负数的情况.
假如用原码来计算(×)
如果我们直接用原码来表示负数,那么运算就会出现问题.
例如,要计算-1+1,用原码表示就是:
// -1 1000 0001
// +1 0000 0001
// 计算结果 1000 0010
这个结果显然是错误的,因为1000 0010的原码表示的是-2,而不是0. 这是因为原码的符号位参与了运算,导致了进位的错误.
假如用反码来计算(×)
如果我们用反码来表示负数,那么运算问题就会稍微好一点.
例如,要计算-1+1,用反码表示就是:
// -1 1111 1110
// +1 0000 0001
// 计算结果 1111 1111
这个结果看起来是正确的,因为1111 1111的反码表示的是0.
但是,如果我们要计算-1-1,用反码表示就是:
// -1 1111 1110
// -1 1111 1110
// 计算结果 1111 1100
这个结果就是错误的,因为1111 1100的反码表示的是-3,而不是-2. 这是因为反码的符号位没有进位(或者说是进的那一位被舍弃了,相加完本来是1 1111 1100,但是只有8个位,因此要发生截断,只保留低8位最高位被舍弃,于是得到1111 1100),导致了结果的错误.
假如用补码来计算(√)
如果我们用补码来表示负数,那么运算问题就会被完美地解决.
例如,要计算-1+1,用补码表示就是:
// -1 1111 1111
// +1 0000 0001
// 计算结果 0000 0000
这个结果是正确的,因为0000 0000的补码表示的是0.
同样,要计算-1-1,用补码表示就是:
// -1 1111 1111
// -1 1111 1111
// 计算结果 1111 1110
这个结果同样是正确的,因为1111 1110的补码表示的是-2. 这是因为补码的符号位和数值位都参与了运算,进位的结果是正确的.
因此,我们可以看到,补码的优势在于它可以使得加法运算不区分正数和负数,而且不会出现错误的运算结果. 这就是为什么计算机内部通常用补码来表示整数的原因.
总结
原码、反码和补码是计算机中表示整数的三种方法,它们的作用是为了方便计算机进行整数的加减运算. 原码是最直观的表示方法,但是会导致加法运算的错误. 反码是对原码的改进,但是仍然存在问题. 补码是对反码的进一步改进,可以完美地解决加法运算的问题. 因此,计算机内部通常用补码来表示整数.
感谢大家花时间阅读,如有错误欢迎在评论区指出!