根据原码求补码:
正数的补码和它的原码相同;
负数的补码是将原码的符号位保持不变,其余各位取反,然后加1,就得到其补码;
如:求-1(10000001b)原码的补码。
按照”取反加一”计算:
-1的原码(10000001b)→按符号位保持不变其余各位取反,得到(11111110b)→加1后得到(11111111b)
所以-1的补码是(11111111b)。
根据补码求原码:
已知一个数的补码,求原码的操作分两种情况:
⑴如果补码的符号位为“0”,表示是一个正数,其原码就是补码。
⑵如果补码的符号位为“1”,表示是一个负数,那么求给定的这个补码的补码就是要求的原码。
如:-1的补码是(11111111b)→按符号位保持不变其余各位取反,得到(10000000b)→加1后得到(10000001b)
所以-1的”补码的补码”就是原码(1000001b)。
(3) 如果补码的符号位为“1”,表示是一个负数,那么补码减1,再将符号位保持不变其余各位取反
-1的补码是(11111111b)→减1(11111110b)→将符号位保持不变其余各位取反(10000001b)
补充:
1、阿拉伯数字加减计算原理
在我们日常生活用到的“一位数”中,正数的最大数值为9,最小数值为0;负数的最大数值为-0,最小数值为-9;它们称为一位数的原数。
由此可知,一位数的模为10。
一位数的负数的补数,计算原理如下:
-0的补数是10-0=10,由于是“一位数”,所以-0的补数是0;又因为+0的补数是0,所以0的补数是0;
我们知道“-1=0-1”,所以
-1的补数是10-1=9;这就好比是"0-1"不够减,"借10"得到的。
注意:这里借的是模数值,为10。
同理,可以-2~-9的补数;如下:
-2的补数是10-2=8;
-3的补数是10-3=7;
-4的补数是10-4=6;
-5的补数是10-5=5;
-6的补数是10-6=4;
-7的补数是10-7=3;
-8的补数是10-8=2;
-9的补数是10-9=1;
当我们计算“-1+5”时,可以通过计算“-1的补数9”加5得到,由于是“一位数”,“十位上的数值”可以忽略,就可以得到4。
因此可以采用“补数的加法运算”来实现减法计算。
这里只涉及到原数和补数。
在计算机中,由于加法器只能做加法运算,所以采用“补数加法”来实现“减法运算”。这就是计算采用补码的原因。
补数也叫补码,原数也叫原码。
2、“有符号8位二进制数"的补码计算
计算机规定“8位二进制数的最高位”表示符号位,1表示负数,0表示正数,有效位数只有7位二进制数。
原码:
“有符号8位二进制数”的正数原码范围为+0~+127,即0x00~0x7F;
“有符号8位二进制数”的负数原码范围为-0~-127,即0x80~0xFF,这里的0x80是-0的原码,0xFF是-127的原码;
由此可知,在原码中,+0~+127后紧跟着的是-0~-127,即+127和-0相邻。
反码:
“有符号8位二进制数”的正数反码范围为+0~+127,即0x00~0x7F;
“有符号8位二进制数”的负数反码范围为-0~-127,即0xFF~0x80,这里0xFF是-0的反码,0x80是-127的反码;注意:负数原码的反码:除符号位外,按位取反,就可以得到其反码。
由此可知,在反码中,+0~+127后紧跟着的是-127~-0,即+127和-127相邻。
因此,“有符号8位二进制数”的模为256。
补码:
1)、正数+1~+127的补码:等于原码。正数+1~+127的补码范围:0x01~0x7F。
2)、0的补码:
-0的补数是256-0=256=0x100,由于是“8位二进制数”,所以-0的补数是0x00;
注意:该计算方法只能用于书面考试或验证,不能用于计算机程序设计,不要被误导。
又因为+0的补数是0,所以0的补数是0;
因此,0的补码是0x00。
3)、负数-1~-127的补码:
正规算法:负数的补码是将原码的符号位保持不变,其余各位取反,然后加1,就得到其补码;可以用于程序设计。
在书面考试时,可以使用“模减去负数的绝对值的补码”得到其补码,但不能用于程序设计。
我们知道“-1=0-1”,所以
-1的补数是256-1=255=0xFF;这就好比是"0-1"不够减,"借256"得到的(这里借的是模数值)。
注意:该计算方法只能用于书面考试或验证,不能用于计算机程序设计,不要被误导。
同理,可以-2~-127的补数;
注意:这里的补数,就是计算机所讲的补码。
-127的补数是256-127=129=0x81;
-1~-127的补码范围:0xFF~0x81;
4)、负数-128的补码:
我们知道“-128=0-128”,所以
-128的补数是256-128=128=0x80;所以-128的补码为0x80,但是-128没有原码和反码。
注意:该计算方法只能用于书面考试或验证,不能用于计算机程序设计,不要被误导。
通过上面的分析,得到
正数+1~+127的补码范围:0x01~0x7F
0的补码是0x00
负数-1~-128的补码范围:0xFF~0x80;注意:-128没有原码和反码。
3、负数的补码为什么是“负数的原码除符号位外其余位按位取反加1”呢?
我们知道:-1的原码是0x81,-1的反码是0xFE;又由于-1的补数是256-1=255=0xFF,即-1的补码为0xFF,
因此,0xFF-0xFE=1,所以,一般来说,负数的补码是”负数的原码“除符号位外,其余位按位取反加1,才是补码。除“最高位为1,其余各位为0”的补码,需要注意,它没有原码,也没有反码。
注意:-128没有原码和反码,在计算时,需要注意。
注意:在使用"模"减去“负数的绝对值”得到的补码,该计算方法只能用于书面考试或验证,不能用于计算机程序设计,不要被误导。
4、根据补码求原码
#include <iostream>
union Char_TYPE
{ unsigned char U8_Data;
char S8_Data;
};
void value_commutation1(unsigned char dat)
{
unsigned char myOriginalCode;
char flag;
union Char_TYPE s8Data;
unsigned char i;
myOriginalCode=dat;
myOriginalCode = (unsigned char)(myOriginalCode&0xFF);//保留最低8位
if( (unsigned char)(dat&0x80) != 0x80 )//0和正数的补码
{
flag=1;//正数
s8Data.U8_Data=myOriginalCode;//得到原码
printf("补码为%u,原码是0x%02x\r\n",s8Data.U8_Data,myOriginalCode);
}
//计算负数原码开始
if(dat==0x80)//当前为-128的补码
{
printf("补码为0x80,即-128没有原码!!!\r\n");
}
else
{
if(dat&0x80)//当前为“非-128”的负数补码
{
myOriginalCode = myOriginalCode -1;//补码减1,得到反码
myOriginalCode = (unsigned char)(~myOriginalCode); //反码按位取反,得到原码
myOriginalCode = (unsigned char)(myOriginalCode&0x7F);//保留最低7位
flag=-1;//负数
s8Data.S8_Data=(char)(flag*myOriginalCode);//得到补码
myOriginalCode=(unsigned char)(myOriginalCode|0x80);//得到原
printf("补码为%u,原码是0x%02x\r\n",s8Data.U8_Data,myOriginalCode);
}
}
//计算负数原码结束
}
int main() {
using namespace std;
unsigned int i;
unsigned char d;
d=255;
for(i=0;i<256;i++)
{
value_commutation1(d);
d--;
}
cout << "hello world,你好!" << endl;
cout << "OK!" << endl;
return 0;
}
g++ main.cpp -o main 执行编译main.cpp
./main 执行main.exe