原码、补码

本文深入探讨了计算机中整型数的表示方法,重点讲解了补码的概念及其在负数表示中的应用。通过实例说明了如何利用补码进行加减运算,避免了传统减法的复杂性,展现了补码在简化计算过程中的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

计算机的整型数可以分为有符号数和无符号数。有符号数使用最高位作为符号位。以一个字节(8bits)的存储为例。无符号为表示区间为[0, 255], 有符号数为[-128, 127]。
计算机二进制表示中,整数常用补码表示。正整数时补码和原码是等价的。

原码表示法

使用最高位作为符号位,其余位按照正常的换算方式。例如+1,-1分别表示为0000 0001,1000 0001。两者只有符号为不同。原码表示的区间为[-127, +127]。

补码表示法

正数的补码等于原码,负数的补码等于对应正数的取反加一。
举例来说,+127的补码为0111 1111,-127的补码是1000 0001。
这让负数补码看起来很反直觉。给定一个负数补码,我想知道对应的值,得减一取反得到绝对值再加上负号。这有的加一,有的减一的完全反应不过来。
其实有一种符合直觉的看法,先定义正数补码然后根据正数定义负数补码。基于
x+(−x)=0x+(-x)=0x+(x)=0
xxx为正数,−x-xx就是负数,上式表示为正数加上负数。假设我们已经定义好了正数补码,比如+127(0111 1111)。我们将负数补码表示定义为与对应正数补码表示相加等于零的数。因此负数应该表示为(1000 0001),这就是-127。
1000 0001的计算步骤分为两步,

  • 第一找到一个数与对应正数相加使二进制变成全1。
    01111111+10000000=111111110111\quad1111 + 1000\quad0000=1111\quad111101111111+10000000=11111111
    这是得到1000 0000。
  • 接着再让1111 1111溢出,变成真正的零值。
    01111111+10000000+00000001=11111111+00000001=1000000000111\quad1111 + 1000\quad0000 + 0000\quad0001 \\ = 1111\quad1111 + 0000\quad0001 \\ =1\quad0000\quad000001111111+10000000+00000001=11111111+00000001=100000000
    把溢出位置扔掉就是最终的结果。
    上面是从正数算负数,那么从负数算正数也可以使用同样的办法,压根不用考虑到底是加一还是减一。
    举个例子:
    -127(1000 0001) -> 0111 1110+0000 0001->0111 1111(+127)
    +127(0111 1111)-> 1000 0000 + 0000 0001 -> 1000 0001(-127)
    所以不管从正数推负数还是负数推正数都只用加一操作。

用正负相加等于零的方式还带来一个好处,不需要减法。
对任意 x−yx-yxy看成x+(−y)x+(-y)x+(y),例如1−1271-1271127:
1−127=(00000001)−(01111111)=10000010=1+(−127)=(00000001)+(10000001)=100000101-127=(0000\quad0001) - (0111\quad1111)\\ =1000\quad0010\\ =1+(-127)\\ =(0000\quad0001)+ (1000\quad0001)=1000\quad0010\\ 1127=(00000001)(01111111)=10000010=1+(127)=(00000001)+(10000001)=10000010
做减法的时候如果不够减就向高位借,实在不够就向溢出位借。
总结上述操作就是先定义正数,使用x+(−x)=0x+(-x)=0x+(x)=0的办法来定义对应负数,并且等于零是用数值溢出的办法得到的,计算时将减法转换为加法,同时上述操作符号位也都参与计算。

以上的操作似乎很一致,并且符合直觉。但是有一个数是例外,-128。8bits 补码表示的区间是[-128, 127], +128是没有定义的,-128也就没办法用上述的办法定义。
用补充的办法将这个边界值定义为 1000 0000,试着用上面的办法计算其对应的值,我们发现其对应正值还为1000 0000,也就是说符号为仍为1。所以这个边界值是上述转换方法的一个bug,但是不影响计算,因为符合借位计算的思想,也符合加周期取模的思想。

<think>嗯,用户想了解原码补码的概念以及转换方法,还有计算机表示法。首先,我需要回忆一下原码、反码和补码的基本定义。原码应该是最直接的二进制表示,符号位在最高位,0正1负。比如,+5是00000101,-5是10000101。对吗? 接下来是反码,正数的反码和原码相同,负数的反码则是符号位不变,其他位取反。比如-5的原码是10000101,反码就是11111010。然后补码的话,正数补码原码一样,负数的补码是反码加1。所以-5的补码应该是11111011。这里可能需要确认一下步骤是否正确,用户提供的引用中也提到补码等于反码加1,特别是负数的部分。 然后转换方法,原码补码。如果是负数的话,先取反码再加1。那补码原码的话,是不是同样的操作?比如补码补码等于原码,引用1里也提到了这一点。例如,补码11111100再取反加1,就会得到原码10000100,也就是-4。这个例子对吗?可能需要检查一下步骤是否正确。 还有用户可能想知道为什么计算机使用补码。根据引用3,补码可以让符号位参与运算,简化运算规则,特别是减法转加法,这样硬件设计更简单。这点很重要,需要解释清楚补码的优势。 另外,用户提供的引用中提到,虽然补码在底层使用,但高级语言里还是用原码,这可能是因为程序员不需要直接处理补码,编译器会自动处理转换。这部分可能需要提到。 应用场景的话,补码用于计算机的算术运算,比如加减法,避免处理符号的复杂性。原码可能在显示或者输入输出时使用,但运算时用补码。需要明确区分两者的使用场景。 可能用户的问题还包括如何手动转换,或者具体的例子,比如给定的数值如何转换。例如,用户给的例子-4的原码是10000100,反码是11111011,补码是11111100。需要确认这些步骤是否正确,以及转换过程中的细节,比如符号位不变,其他位取反加1。 还需要注意位数的限制,比如8位二进制数,最高位是符号位,所以范围是-128到127,补码的情况下。原码和反码的范围可能不同,比如原码的8位范围是-127到+127,而补码可以表示-128,这点需要说明。 可能用户还会混淆原码补码之间的转换步骤,比如负数补码原码是否需要再次取反加1,还是直接保留符号位取反加1。根据引用1,补码补码等于原码,所以转换方法是相同的,不管原数是什么,补码原码都是取反加1,符号位不变? 总结下来,我需要分步骤解释原码、反码、补码的定义,转换方法,以及计算机为什么使用补码。同时,结合用户提供的引用内容,确保引用正确,例如补码的运算优势,转换步骤的例子是否正确。可能还需要指出常见误区,比如补码的范围比原码大,或者转换时的注意事项。</think>### 原码补码与计算机表示法 #### 1. 原码 (Sign-Magnitude) - **定义**:原码是二进制数的直接表示形式,最高位为符号位(0表示正,1表示负),其余位为数值位。 - 例如:十进制数 $-4$ 的8位原码为 $1000\ 0100$[^1]。 - **特点**: - 直观,但加减运算需处理符号位,硬件实现复杂。 - 存在“+0”和“-0”两种零的表示(如 $0000\ 0000$ 和 $1000\ 0000$)。 --- #### 2. 补码 (Two’s Complement) - **定义**:补码是计算机中表示有符号整数的标准方式,正数的补码原码相同;负数的补码为其反码加1[^2]。 - **反码**:符号位不变,数值位按位取反。 - 例如:十进制数 $-4$ 的补码转换过程: 原码 $1000\ 0100$ → 反码 $1111\ 1011$ → 补码 $1111\ 1100$[^1]。 - **特点**: - 符号位参与运算,减法可转换为加法,简化硬件设计[^3]。 - 无“-0”,补码范围比原码多一个负数(如8位补码范围为 $-128$ 至 $127$)。 --- #### 3. 原码补码的转换 - **原码补码**: 1. **正数**:补码 = 原码。 2. **负数**: - 取反码(符号位不变,数值位取反)。 - 反码 + 1。 - **补码原码**: - 方法与“原码补码”相同:对补码再次取反码后加1。 - 例如:补码 $1111\ 1100$ → 反码 $1111\ 1011$ → 原码 $1000\ 0100$。 --- #### 4. 计算机为何使用补码? 1. **统一加减法**:减法可转换为加法运算(如 $A - B = A + (-B)$),无需额外电路。 2. **消除符号位冲突**:符号位直接参与运算,无需单独处理。 3. **扩展性**:补码能表示更广泛的数值范围(如8位补码可表示 $-128$)。 --- #### 示例:-7的8位补码计算 1. 原码:$1000\ 0111$ 2. 反码:$1111\ 1000$ 3. 补码:$1111\ 1001$ ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值