计算机中的位操作、补码、反码、原码

本文深入讲解了计算机中补码的概念及其应用,包括正负数的补码表示方法、补码与原码之间的转换规则,以及如何利用补码进行加减乘除等基本运算。同时还介绍了位操作的具体实现。

1、说明

计算机中的符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分。
在计算机中,数值一律用补码来表示和存储。原因在于,使用补码可以将符号位和数值域同一处理;同时,加法和减法也可以统一处理。此外补码和原码相互转换,其运算过程是相同的,不需要额外的硬件电路。

基本原理:
1. 一个负数(或原码)与其补数(补码)相加,和为模。
2. 对一个整数的补码再求补码等于该整数自身。
3. 补码的正零与负零表示方法相同。

1.1模

“模”是指一个计量系统的计数范围。如时钟等。计算机可以看成一个计量机器,它也有一个范围,即都存在一个“模”。
例如:
时钟的范围是0-11,模=12 表示n为的计算机计量范围是0~2^(n)-1,模=2^(n).
模实际上是计量器产生的溢出量,它的值在计量器上表示不出来,计量器只能表示出模的余数。任何有mo的计量器,均可化减法为加法运算。

例如:假设当前时针指向10点,而准确时间是6点,调整时间可以有以下两种拨法:一种是倒拨4小时,即10-4=6;另一种是顺拨8小时:10+8=12+6=6.

在以12模的系统中,加8和减4效果是一样的。因此凡是减4运算可以用加8来代替。对“模”而言,8和4互为补数,实际上,以12模的系统中,11和1,10和2,9和3,7和5,6和6都有这个特性。共同的特点是两者相加等于模。

对于计算机,其概念和方法完全一样。n位计算机,设n=8,所能表示的最大数为11111111,若再加1成为100000000,但因为只有8位,则最高位丢失。又回到了00000000,所以8位二进制系统的模为2^8.在这样的系统中减法问题也可以转化为加法问题,只需把减数用相应的补数表示就可以了。把补数用到计算机对数的处理上,就是补码。

1.2 补码

1)正整数的补码
正整数的补码是其二进制表示,与原码相同。
2)负数的补码
求负数的补码,将其对应正数二进制上表示所有位取反后加1.

Eg:求-5的补码:
-5对应正数5(00000101)->所有位取反(11111010)->加1(11111011)
所以-5的补码是11111011

eg:数0的补码表示是唯一的
[+0]补=[+0]反=[+0]原=00000000
[-0]补=11111111+1=00000000

3)补码转化为原码:
已知一个数的补码,求原码的操作就是对该补码再求补码:
 如果补码的符号位为“0”,表示是一个正数,则其原码就是补码。
 如果补码的符号位为“1”,表示是一个负数,那么求给定这个补码的补码就是要求的原码。
Eg:已知一个补码为11111001,则原码为10000111(-7).
因为符号位为“1”,表示是一个负数,所以该位不变,仍为“1”。
其余七位1111001取反后为0000110;再加1,所以是10000111.

4)补码的绝对值
eg:-65的补码是10111111
在计算机内,如果一个二进制数,其最左边位是1,则我们可以判定它为负数,并且是用补码表示。若要得到一个负二进制补码的数值,只要对补码全部取反并加1,就可以得到其数值。
10111111(-65的补码)->(各位取反)->01000000->(加1)->01000001(+65)

1.3 代数加减运算

1)补码加法
[X+Y]补=[X]补+[Y]补
eg: X=+0110011(51),Y=-0101001(-41),求[X+Y]补
[X]补=00110011 [Y]补=11010111
[X+Y]补=[X]补+[Y]补 = 00110011 + 11010111 = 00001010
注:因为计算机中运算器的位长是固定的(定长运算),上述运算中产生的最高位将丢掉,所以结果不是100001010而是00001010 = 10

2)补码减法
[X-Y]补 = [X]补-[Y]补=[X]补+[-Y]补
eg: 1-1[十进制]
1的原码:00000001 转换为补码是:00000001
-1的原码:10000001 转换为补码是:11111111
1+(-1) = 00000001 + 11111111 = 00000000(0)

eg: -7-(-10)[十进制]
-7的补码:11111001 -(-10)的补码:-10的原码为10001010,-(-10)的原码为:00001010
-(-10)的补码就是其原码:00001010
-7-(-10) = -7+10 = 11111001+00001010 = 00000011=3

3)补码乘法
补码的乘法不具备[X*Y]补=[X]补*[Y]补的性质。但是[X*Y]补==[X]补*Y,所得结果再取补码。例如x=101,y=011. [x*y]补=

1.4 位操作的种类

所有的位操作,操作的都是补码。
1)左移操作
左移操作”<<”将证书最高位挤掉,而在右端补0。
左移就相当于乘2,而不管整形是否有符号。
Eg: a = 12 求a<<1
a=12=00001100[补]
a<<1 = 00011000[补] = 16+8 = 24[十进制]

2)右移操作
右移操作”>>”是在整数的高位挤进去一个0或1进去,而整数右边的1或0被挤掉。 对于有符号数,若最高位是1,则高位挤进1;最高位是0则挤进去0

Eg: short int a = -2; 求 a>>1
a=-2的原码是10000010->11111110 [补]
a>>1=11111111[补]->10000001[原] = -1[十进制]

Eg: short int a = 12; 求a>>1
A = 12 的原码是00001100->00001100[补]
a>>1=00000110[补]->00000110[原]=6[十进制]

右移就相当于除2,无论整形是否有符号。

3)位与操作
位与操作”&”是将两个操作数每一位做与操作。
&操作是两个数都为1的时候,结果才是1,否则为0
Eg: int a = 12, b=6 求a&b
a=12= 00001100
b=6= 00000110
a&b= 00000100=4

eg: int a = -12,b=6 求a&b
a=-12= 10001100[原] ->11110100[补]
b=6= 00000110
a&b=00000100=4

eg: int a=-12,b=-6 求a&b
a=-12=10001100[原]->11110100[补]
b=-6 = 10000110[原] ->11111010[补]
a&b= 11110000[补]->10010000[原]->-16[十进制]

4)位或操作
位或操作”|”是将两个操作数的每一位做或操作。
|操作是两个数中有一个数为1则结果就是1,否则为0
eg:int a=12,b=6 求a|b
a=12= 00001100
b=6= 00000110
a|b= 00001110 = 14

eg: a=-12,b=-6 求a|b
a=-12= 11110100
b=-6= 11111010
a|b= 11111110[补]->10000010[原]=-2

5) 位异或操作
位异或”^”操作是将两个操作数每一位做异或操作,异或也称对称和,或称无进位加等,若两个操作数相等(都为0或都为1,则其值为0,否则为1)。

Eg: a=12,b=6 求a^b
a=12= 00001100
b=6= 00000110
a^b= 00001010=10

eg: a=-12,b=-6 求a^b
a=-12= 11110100
b=-6= 11111010
a^b= 00001110=14

6) 位反操作
位反”~” 操作是将一个操作数每一位取反,0变成1,1变成0.
Eg: int a=12 求a=~a
a= 12= 00001100
~a= 11110011->10001101=-13

### 补码反码原码的概念及其区别与联系 #### 1. 原码 (Original Code) 原码是最直观的一种编码形式,其特点是符号位明确表示数值的正负。对于正数,符号位为 `0`;对于负数,符号位为 `1`,其余部分则直接表示绝对值。 例如: - 正数 `[+7]` 的原码为:`00000111` - 负数 `[-7]` 的原码为:`10000111` 这种编码方式简单易懂,但存在两个主要缺点: - 零有两位表示法(即 `+0` 和 `-0`),这增加了硬件设计复杂度。 - 加减法操作无法统一处理,需额外判断符号位[^1]。 --- #### 2. 反码 (Complement Code) 反码主要用于简化补码的计算过程,是一种过渡性的编码形式。具体定义如下: - **正数**:反码等于原码- **负数**:符号位保持不变,其他各位按位取反(即将 `0` 替换为 `1`,将 `1` 替换为 `0`)。 例如: - 正数 `[+7]` 的反码仍为:`00000111` - 负数 `[-7]` 的反码为:`11111000` 需要注意的是,反码本身并不适合直接参与运算,而更多是用来辅助求解补码的过程[^2]。 --- #### 3. 补码 (Two's Complement Code) 补码的设计目的是为了实现加减法的统一切换机制,从而提高计算机内部数据处理效率。以下是具体的规则: - **正数**:补码与其原码相同; - **负数**:基于原码,先将其余部分逐位取反得到反码,再对反码末尾加 `1` 即可获得补码。 继续以上述例子说明: - 正数 `[+7]` 的补码仍是:`00000111` - 负数 `[-7]` 的补码为:`11111001` 通过引入补码体系,不仅消除了零的双重表达问题,而且使得所有的整数都可以采用相同的逻辑电路完成加减运算,极大地优化了硬件结构[^3]。 --- #### 4. 它们之间的关系总结 | 编码类型 | 特点 | |-----------|------------------------------------------------------------------------------------------| | 原码 | 符号位显式区分正负,便于人类理解,但在机器层面难以高效执行 | | 反码 | 是一种中间状态,尤其适用于从原码补码转化的过程中 | | 补码 | 实现了加减法的一体化支持,成为现代计算机存储和运算的核心基础 | 三者之间存在着紧密关联,其中补码因其实用性和优越性能脱颖而出,广泛应用于当今各类电子设备之中。 ```python def get_complements(num, bits=8): """获取给定数字num在bits位下的原码反码以及补码""" if num >= 0: original_code = bin(num)[2:].zfill(bits) complement_code = original_code two_complement = original_code else: abs_num = abs(num) original_code = '1' + bin(abs_num)[2:].zfill(bits - 1) inverted_bits = ''.join(['1' if b == '0' else '0' for b in original_code[1:]]) complement_code = '1' + inverted_bits two_complement_int = int(complement_code, 2) + 1 two_complement = bin(two_complement_int)[2:].zfill(bits) return f"original code:{original_code}, complement code:{complement_code}, two's complement:{two_complement}" print(get_complements(-7)) ``` 上述代码展示了如何针对任意指定长度比特位生成相应三种编码形式的方法实例。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值