方便起见,这里举例全部取8位二进制数
定义:
正数原、反、补一致,不说
负数
原:-7:1000 0111
反:-7:1111 1000 即符号位不变,其他取反
补:-7:1111 1001 即在反码基础上加一
补一个原码直接(不通过反码)求补码的方法,从右往左,遇0不变,遇第一个1也不变,接着逐个(不包括符号位)取反,符号位保留,即可。
另附:补码的补码是原码
说明几个让人疑惑的特例:
数字 | 原码 | 反码 | 补码 |
+0 | 0000,0000 | 0000,0000 | 0000,0000 |
-0 | 1000,0000 | 1111,1111 | 0000,0000 |
-128 | not exist | not exist | 1000,0000 |
上表可以看出,+0,-0是公用一个补码的,这样才是科学的,但机器中用补码表示数值是另外一个主因,即引入补码后,减法运算可以用加法实现。
例如:17+(-3)
原码运算 | 补码运算 |
0001,0001 | 0001,0001 |
1000,0011 | 1111,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);
}