我只是好奇为什么要使用二进制的补码来表示-1:翻转位并加上1?
-1用11111111(二进制补码)表示,而不是(对我来说更直观的)10000001,这是二进制1,第一个位作为负标志。
免责声明:我不依靠二进制算术来工作!
我只是好奇为什么要使用二进制的补码来表示-1:翻转位并加上1?
-1用11111111(二进制补码)表示,而不是(对我来说更直观的)10000001,这是二进制1,第一个位作为负标志。
免责声明:我不依靠二进制算术来工作!
不同类型的表示法有:
- 无符号数表示法用于表示正数。
- 带符号数表示法用于表示正数和负数。在带符号数表示法中,MSB位表示符号位,其余位表示数字。当MSB为0时,表示数字为正;当MSB为1时,表示数字为负。
带符号数表示法的问题在于0有两个值。
反码表示法的问题在于0有两个值。
但是,如果我们使用补码表示法,则只有一个值为0,这就是为什么我们使用补码形式表示负数的原因。
好的,你的意图并不是要反转二进制数的所有位。实际上,你想要做的是从1中减去每个数字。很幸运,从1中减去1的结果是0,从1中减去0的结果是1。因此,翻转比特实际上就是进行这种减法。
但是,为什么你要计算每个数字与1之间的差异呢?实际上并不是这样的。你真正的意图是计算给定的二进制数与另一个二进制数之间的差异,两个二进制数具有相同的位数,但只包含1。例如,如果你的数字是10110001,当你翻转所有这些位时,你实际上是在计算(11111111 - 10110001)。
这解释了计算二进制补码的第一步。现在让我们把第二步——加1——也纳入考虑。
将上述二进制方程式加1:
11111111 - 10110001 + 1
你会得到什么?这个:
100000000 - 10110001
这就是最终的方程式。通过执行这两个步骤,你试图找到这个最终差异:将二进制数从另一个具有一个额外位数且只在最高有效位位置包含零的二进制数中减去。
但我们为什么真的渴望这种差异呢?嗯,从现在开始,我想如果你阅读维基百科文章会更好。
00000001
的整数中减去任何其他最低8位为0000000
的整数将产生一个最低8位为11111111
的整数。在数学上,值-1将是一个无限长的1字符串,但特定整数类型范围内的所有值都将在某个点过后成为全1或全0,因此计算机方便地将数字的最高有效位作为代表无限数量的1或0进行“符号扩展”。
二进制补码是处理大于二进制机器自然字长的类型时唯一有效的带符号数表示法,因为在执行加法或减法时,代码可以获取每个操作数的最低块,计算结果的最低块,并存储它,然后加载每个操作数的下一个块,计算结果的下一个块,并存储它,以此类推。因此,即使处理器要求所有加法和减法都通过单个8位寄存器进行,也可以相对高效地处理32位带符号数(当然比使用32位寄存器慢,但仍可行)。
当使用C标准允许的任何其他带符号表示时,结果的每个位都可能受到操作数的任何位的影响,这使得必须将整个值一次性保存在寄存器中,否则在计算后需要跟随额外的步骤,在至少某些情况下需要读取、修改和重写结果的每个块。
对于加法和减法,我们仅执行加法操作。 对于加法,我们将第二个操作数添加到第一个操作数。 对于减法,我们将第二个操作数的2的补码添加到第一个操作数。
使用2的补码表示法,我们不需要单独的数字组件来进行减法运算-仅使用加法器和补码器即可。
为什么使用二进制补码来表示负数而不是一的补码系统,其中一个令人满意的答案是,二进制补码系统解决了一的补码系统中存在的“0的多重表示”和“绕位进位”的问题。
欲了解更多信息,请访问https://en.wikipedia.org/wiki/Signed_number_representations。