问一个基本的问题。
负数在计算机中如何表示?
举例来说,+8在计算机中表示为二进制的1000,那么-8怎么表示呢?
很容易想到,可以将一个二进制位(bit)专门规定为符号位,它等于0时就表示正数,等于1时就表示负数。比如,在8位机中,规定每个字节的最高位为符号位。那么,+8就是00001000,而-8则是10001000。
但是,随便找一本《计算机原理》,都会告诉你,实际上,计算机内部采用2的补码(Two's Complement)表示负数。
什么是2的补码?
它是一种数值的转换方法,要分二步完成:
第一步,每一个二进制位都取相反值,0变成1,1变成0。比如,00001000的相反值就是11110111。
第二步,将上一步得到的值加1。11110111就变成11111000。
所以,00001000的2的补码就是11111000。也就是说,-8在计算机(8位机)中就是用11111000表示。
不知道你怎么看,反正我觉得很奇怪,为什么要采用这么麻烦的方式表示负数,更直觉的方式难道不好吗?
昨天,我在一本书里又看到了这个问题,然后就花了一点时间到网上找资料,现在总算彻底搞明白了。
2的补码的好处
首先,要明确一点。计算机内部用什么方式表示负数,其实是无所谓的。只要能够保持一一对应的关系,就可以用任意方式表示负数。所以,既然可以任意选择,那么理应选择一种最方便的方式。
2的补码就是最方便的方式。它的便利体现在,所有的加法运算可以使用同一种电路完成。
还是以-8作为例子。
假定有两种表示方法。一种是直觉表示法,即10001000;另一种是2的补码表示法,即11111000。请问哪一种表示法在加法运算中更方便?
随便写一个计算式,16 + (-8) = ?
16的二进制表示是 00010000,所以用直觉表示法,加法就要写成:
00010000
+10001000
---------
10011000
可以看到,如果按照正常的加法规则,就会得到10011000的结果,转成十进制就是-24。显然,这是错误的答案。也就是说,在这种情况下,正常
的加法规则不适用于正数与负数的加法,因此必须制定两套运算规则,一套用于正数加正数,还有一套用于正数加负数。从电路上说,就是必须为加法运算做两种电
路。
现在,再来看2的补码表示法。
00010000
+11111000
---------
100001000
可以看到,按照正常的加法规则,得到的结果是100001000。注意,这是一个9位的二进制数。我们已经假定这是一台8位机,因此最高的第9位是
一个溢出位,会被自动舍去。所以,结果就变成了00001000,转成十进制正好是8,也就是16 + (-8)
的正确答案。这说明了,2的补码表示法可以将加法运算规则,扩展到整个整数集,从而用一套电路就可以实现全部整数的加法。
2的补码的本质
在回答2的补码为什么能正确实现加法运算之前,我们先看看它的本质,也就是那两个步骤的转换方法是怎么来的。
要将正数转成对应的负数,其实只要用0减去这个数就可以了。比如,-8其实就是0-8。
已知8的二进制是00001000,-8就可以用下面的式子求出:
00000000
-00001000
---------
因为00000000(被减数)小于0000100(减数),所以不够减。请回忆一下小学算术,如果被减数的某一位小于减数,我们怎么办?很简单,问上一位借1就可以了。
所以,0000000也问上一位借了1,也就是说,被减数其实是100000000,算式也就改写成:
100000000
-00001000
---------
11111000
进一步观察,可以发现100000000 = 11111111 + 1,所以上面的式子可以拆成两个:
11111111
-00001000
---------
11110111
+00000001
---------
11111000
2的补码的两个转换步骤就是这么来的。
为什么正数加法适用于2的补码?
实际上,我们要证明的是,X-Y或X+(-Y)可以用X加上Y的2的补码完成。
Y的2的补码等于(11111111-Y)+1。所以,X加上Y的2的补码,就等于:
X + (11111111-Y) + 1
我们假定这个算式的结果等于Z,即 Z = X + (11111111-Y) + 1
接下来,分成两种情况讨论。
第一种情况,如果X小于Y,那么Z是一个负数。这时,我们就对Z采用2的补码的逆运算,求出它对应的正数绝对值,再在前面加上负号就行了。所以,
Z = -[11111111-(Z-1)] = -[11111111-(X + (11111111-Y) + 1-1)] = X - Y
第二种情况,如果X大于Y,这意味着Z肯定大于11111111,但是我们规定了这是8位机,最高的第9位是溢出位,必须被舍去,这相当于减去100000000。所以,
Z = Z - 100000000 = X + (11111111-Y) + 1 - 100000000 = X - Y
这就证明了,在正常的加法规则下,可以利用2的补码得到正数与负数相加的正确结果。换言之,计算机只要部署加法电路和补码电路,就可以完成所有整数的加法。
(http://www.ruanyifeng.com/blog/2009/08/twos_complement.html)
分享到:
相关推荐
本文将深入探讨2s补码的概念,以及如何使用MATLAB实现2s补码到十进制的转换。 首先,让我们理解2s补码的工作原理。对于n位的2s补码,最大的正数表示为1111...1111(n个1),而最小的负数表示为1000...0000。正数的2...
在本实验"原码转补码(逻辑门实现)"中,我们聚焦于如何通过基本的逻辑门(如与门、或门、非门和异或门)来实现三位数的原码转换为补码的过程。这个过程可以分为几个步骤: 1. **确定符号位**:首先,我们需要识别...
我们常见的有十进制(基数为10)、二进制(基数为2)和十六进制(基数为16)。二进制是计算机内部处理数据的基础,而十六进制则是方便人类理解和表示二进制的一种方式,因为每四位二进制可以对应一个十六进制数字。 ...
2的补码是一种在计算机系统中表示有符号整数的方法,尤其用于处理负数。它的基本原理是通过取反加1的方式来表示负数,确保在二进制运算中正负数可以按照同样的规则进行加减操作。 补码的定义: 在2的补码记数法中,...
以下是关于这些概念的详细解释: 1. **原码**: 原码是最直接的二进制表示方式,其中最高位(符号位)用于表示数值的正负。对于正数,符号位为0;对于负数,符号位为1。其余位表示数值的绝对值。例如,正数5的原码...
Console.WriteLine("从补码回溯的原码: " + Convert.ToString(originalFromComplement, 2)); } } ``` 这段代码首先将-5转换为二进制原码,然后计算其反码和补码,最后通过反码和补码计算回原码。注意,从反码和...
- **加法模式处理**:当 `addMode` 等于2时,需要对 `num2` 进行取反操作,即计算 `num2` 的补码,这一步骤是为了实现减法运算。 - **位级加法运算**: - 首先判断是否为无符号加法,如果是,则在每个操作数前添加...
二进制原码反码补码知识点总结 计算机内部采用的是二进制,只有两个数字用于表示数据,即 0 和 1,所以它的进制原则是满 2 进 1。十进制用的是 0、1、2、3……9 十个数字来表示数据,它的原则是满 10 进 1。 二...
**例2**:求-1的补码表示。 1. **原码**:`10000000000000000000000000000001` 2. **反码**:`11111111111111111111111111111110` 3. **补码**:`11111111111111111111111111111111` 可以看出,-1的补码表示为全1...
2. 负数的补码=原码取反,最低位+1,符号位不变 小数的补码表示方法: 1. 正小数的补码=原码 2. 负小数的补码=原码取反,最低位+1,符号位不变 三、补码的运算规则 补码的运算规则可以分为三种:加法、减法和...
8. 当机器字长为8位时,-105的二进制补码是10010111,这是通过先将十进制-105转换为二进制(-105 = -1 * (2^7 + 2^3 + 2^2) = 10010111),然后设置符号位为1得到的。 9. 十进制数-26的8位二进制补码是11100110,这...
2. 检查最高位(符号位),如果为1,则执行负数的转换过程。 3. 对补码值(不包括符号位)执行位取反操作。 4. 对结果加1,得到负数的原码。 5. 如果最高位为0,那么这个数就是正数,原码和补码相同。 6. 可能会有...
2. **移位操作**:左移操作在有符号整数中会保留符号位,相当于乘以2的幂;右移则有两种方式,逻辑右移(高位用0填充)和算术右移(高位用符号位填充),在处理负数时要特别注意。 3. **比较操作**:比较两个补码数...
关于补码的经典认识,是计算机科学与信息技术领域中一个至关重要的概念,它涉及到二进制数的表示方式,尤其在处理负数时显得尤为重要。补码的引入,旨在解决传统原码表示法在进行算术运算时存在的问题,如加减法不...
例如,加法实验中,输入7和15的补码,得到的和为22的补码,转换为原码为2。减法实验中,输入-8和-5的原码,通过补码运算得到-3的原码。这些结果验证了补码加法器的正确性。 实验后的分析表明,学生通过实际操作不仅...
### 原码和补码基础教程 #### 一、引言 在计算机科学领域,数字的表示方式对于数据处理至关重要。特别是在低级语言编程、硬件设计与算法优化等方面,理解数字的不同编码方式是非常关键的一步。本文将详细介绍原码...
// 进位左移一位,相当于2倍 b = carry ; } return a; } ``` 这个过程模拟了二进制加法的运算,注意这里的“进位”实际上是考虑了补码的特性。通过循环直到没有进位,我们可以得到加法的结果。 此外,还可以...
2. **原码、反码和补码计算**: - **原码**:原码是最直接的二进制表示,正数的最高位(符号位)为0,负数为1,其余位是数值部分。在LabVIEW中,一旦16进制转换为二进制,它就是该数的原码。 - **反码**:对于正数...
- **十进制转二进制**:整数部分采用“除2取余”法,小数部分采用“乘2取整”法。 - **十进制转八进制**:同样适用于上述方法,先转为二进制,再由二进制转八进制。 - **十进制转十六进制**:采用类似的“除16取余”...
输出任意两个数之间每个数值的循环移位或者补码。输入一个左边界数值(下记作a),一个右边界数值(下记作b),选择结果类型,如果选择循环移位,输入循环...起始数值:2 终止数值:4 选择循环移位 输入循环移位:1