关于补码的问题


方便起见,这里举例全部取8位二进制数

定义:

正数原、反、补一致,不说

负数

原:-7:1000 0111

反:-7:1111 1000 即符号位不变,其他取反

补:-7:1111 1001 即在反码基础上加一

补一个原码直接(不通过反码)求补码的方法,从右往左,遇0不变,遇第一个1也不变,接着逐个(不包括符号位)取反,符号位保留,即可。

另附:补码的补码是原码

说明几个让人疑惑的特例:

数字原码反码补码
+00000,00000000,00000000,0000
-01000,00001111,11110000,0000
-128not existnot exist1000,0000





上表可以看出,+0,-0是公用一个补码的,这样才是科学的,但机器中用补码表示数值是另外一个主因,即引入补码后,减法运算可以用加法实现。

例如:17+(-3)

原码运算补码运算
0001,00010001,0001
1000,00111111,1101
1001,0100(-20)1,0000,1110(+14)




原码错的有多离谱就不说了。

显然,在硬件中只要一个加法器,就能实现加、减法运算。

附:原码:The original code 反码:Anti-code 补码:Complement


笔者写了一个源程序,用以测试二进制十进制相互转化和原、反、补码的运算。

// test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "stdlib.h"//引入库,system("pause");用到
#include <cmath>
#include <iostream>
#include <string>
using std::string;

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
	int b_to_d(string p);//二进制转换为十进制函数
	string d_to_b(int n);//十进制转换为二进制函数
	string anticode(string p);//求反码函数
	string complement(string p);//求补码函数
	string binary;
	int decimal=0;
	cout<<"说明:作者技术有限,时间也有限,没有写容错机制,输入二进制时必须是8位‘0’‘1’组成的字串,输入十进制时必须是-128~127之间的数!"<<endl;
	cout<<"先测试二进制向十进制的转换,请输入一个二进制数:"<<endl;
	cin>>binary;
	decimal=b_to_d(binary);
	cout<<"结果为:"<<decimal<<endl;
	cout<<"反码为:"<<anticode(binary)<<endl;
	cout<<"补码为:"<<complement(binary)<<endl;
	cout<<"现测试十进制向二进制的转换,请输入一个十进制数:"<<endl;
	cin>>decimal;
	binary=d_to_b(decimal);
		if(decimal==-128)
		cout<<"-128情况比较特殊,原码反码皆不存在!"<<"补码为:10000000"<<endl;
	else
	{
	cout<<"结果为:"<<binary<<endl;
	cout<<"反码为:"<<anticode(binary)<<endl;
	cout<<"补码为:"<<complement(binary)<<endl;
	}

	system("pause");//程序暂停,避免一闪而过
	return 0;
}

string d_to_b(int n)
{
	string temp="00000000";
	char c;
	int t,yu,i=0;
	if(n>127||n<-128)
	{
		cout<<"麻烦您输入一个-128~127之间的数,谢谢!"<<endl;
	}
	else
	{
		t=n;
		n=std::abs(n);
			while(n>1)
			{
				yu=n%2;
				n=n/2;
				if(yu==1)
					temp[i]='1';
				else
					temp[i]='0';
				i++;
			}
			temp[i]='1';
			if(t==0)
				temp[i]='0';
		if(t>=0)
			temp[7]='0';
		else
			temp[7]='1';
		for(i=0;i<4;i++)
		{
			c=temp[i];
			temp[i]=temp[7-i];
			temp[7-i]=c;
		}
	}
	return temp;
}

string anticode(string p)
{
	if(p[0]=='1')
	{
		for(int i=1;i<8;i++)
		{
			if(p[i]=='0')
				p[i]='1';
			else
				p[i]='0';
		}
	}
	return p;
}

char toggle(char c)//取反函数,注意这个函数没有在主函数声明,这是因为主函数没有用到这个函数,下面的complement用到了,所以在它前面就可以了
{
	if(c=='1')
		return '0';
	else
		return '1';
}

string complement(string p)
{
	bool state=false;
	if(p[0]=='0')
		return p;
	for(int i=7;i!=0;i--)
	{
		if(state)
			p[i]=toggle(p[i]);
		if(p[i]=='1')
			state=true;
	}
	if(!state)
		return "00000000";
	return p;
}


int b_to_d(string p)
{
	int temp=0;
	int i=1;
	while(i<8)
	{
		if(p[i]=='1'||p[i]=='0')
		{
			if(p[i]=='1')
				temp=temp+std::pow((double)2,(double)(7-i));
		}
		else
		{
			cout<<"您必须严格输入8位二进制数,程序比较小,没有容错机制!"<<endl;//检测到输入错误,提示错误并立刻跳出
		}
		i++;
	}
	if(p[0]=='0')
		return temp;
	else
		return (0-temp);
}


### 补码的概念及其在计算机科学中的应用 #### 什么是补码补码是一种用于表示整数(包括正数和负数)的二进制编码方式,在计算机中广泛应用。它不仅简化了加法和减法的操作,还解决了负数取模的问题,使计算机能够更高效地处理数值[^1]。 对于一个给定的位宽 \( n \),补码的具体定义如下: - **正数**:其补码与其原码相同。 - **负数**:其补码等于该数绝对值的二进制形式按位取反后再加1。 这种设计的优点在于统一了零的表示方式,并消除了早期计算机系统中存在的二义性问题[^2]。 --- #### 如何计算补码? 假设我们有一个8位的二进制数: 1. **正数的补码** 正数的补码直接为其二进制表示。例如,\( +5 \) 的二进制为 `0000 0101`,因此它的补码也是 `0000 0101`。 2. **负数的补码** 负数的补码可以通过以下步骤获得: - 将该数的绝对值转换为二进制; - 对每一位取反(称为反码); - 反码加1即可得到补码。 例如,\( -5 \) 的补码计算过程如下: - \( |−5| = 5 \),对应的二进制为 `0000 0101`; - 按位取反得 `1111 1010`; - 加1后得 `1111 1011`,这就是 \( −5 \) 的补码[^4]。 --- #### 补码的应用场景 ##### 1. 简化算术运算 在计算机硬件层面,使用补码可以使加法器电路同时支持加法和减法操作。这是因为减去一个数等同于加上这个数的补码[^2]。例如: \[ (-5) + (+3) = (-2) \] 用补码表示并进行计算: - \( -5 \) 的补码为 `1111 1011`; - \( +3 \) 的补码为 `0000 0011`; - 它们的和为 `1111 1110`,这正是 \( -2 \) 的补码。 ##### 2. 编程中的补码实现 以下是 Python 中的一个简单函数,用来计算任意整数的补码(假定位宽为8位): ```python def to_twos_complement(n, bits=8): if n >= 0: return bin(n)[2:].zfill(bits) else: mask = (1 << bits) - 1 return bin((n & mask))[2:].zfill(bits) print(to_twos_complement(-5)) # 输出 '11111011' ``` 此代码利用掩码技术实现了补码的快速计算。 --- #### 总结 补码作为一种高效的二进制表示方法,极大地优化了计算机内部的数据存储与运算效率。无论是硬件还是软件领域,补码都扮演着至关重要的角色。理解补码的工作原理以及如何将其应用于实际编程环境中,有助于开发者更好地掌握底层数据结构的知识。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值