1、原码、反码和补码的表示方法
[-7]原= 1 0000111 B
注意:a. 数0的原码有两种形式:
[+0]原=00000000B [-0]原=10000000B
8位二进制原码的表示范围:-127~+127
(2)反码:
正数:正数的反码与原码相同。
负数:负数的反码,符号位为“1”,数值部分按位取反。
例如: 符号位 数值位
[+7]反= 0 0000111 B
[-7]反= 1 1111000 B
注意:a. 数0的反码也有两种形式,即
[+0]反=00000000B
[- 0]反=11111111B
8位二进制反码的表示范围:-127~+127
(3)补码:
在计算机系统中,数值一律用补码来表示(存储)。
主要原因:使用补码,可以将符号位和其它位统一处理;同时,减法也可按加法来处理。另外,两个用补
码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。
数值的补码表示也分两种情况:
正数:正数的补码和原码相同。
负数:负数的补码则是符号位为“1”,数值部分按位取反后再在末位(最低位)加1。也就是“反码+1”。
[+7]补= 0 0000111 B
[-7]补= 1 1111001 B
2 、已知一个数的补码,求原码的操作分两种情况:
(1)如果补码的符号位为“0”,表示是一个正数,所以补码就是该数的原码。
(2)如果补码的符号位为“1”,表示是一个负数。按照求负数补码的逆过程,数值部分应是最低位减1,然后取反。但是对二进制数来说,先减1后取反和先取反后加1得到的结果是一样的,故仍可采用取反加1 。
例:已知某数X的补码11101110B,试求其原码。
解:由[X]补=11101110B知,X为负数。求其原码表示时,符号位不变,数值部分按位求反,再在末位加1。
1 1 1 0 1 1 1 0 补码
1 0 0 1 0 0 0 1 符号位不变,数值位取反
1 +1
1 0 0 1 0 0 1 0 原码
若字长为8位,则补码所表示的范围为-128~+127。这是一个规定, 10000000这个补码表示的这个数是-128。所以n位补码能表示的范围是-2^(n-1)到2^(n-1)-1,比n位原码能表示的数多一个。
byte类型的范围:(负数最小值,1既是符号位又是值位)
Dec: -128 -1 0 127
Bin: 1000 0000 1111 1111 0000 0000 0111 1111
32位Int类型范围:
Dec: -2147483648 -1 0 2147483647
Hex: 0x80000000 0xFFFFFFFF 0x00000000 0x7FFFFFFF
3、溢出
两个有符号数进行加法运算时,如果运算结果超出可表示的有符号数的范围时,就会发生溢出,使计算结果出错。很显然,溢出只能出现在两个同符号数相加或两个异符号数相减的情况下。
对于加法运算,如果次高位(数值部分最高位)形成进位加入最高位,而最高位(符号位)相加(包括次高位的进位)却没有进位输出时,或者反过来,次高位没有进位加入最高位,但最高位却有进位输出时,都将发生溢出。因为这两种情况是:两个正数相加,结果超出了范围,形式上变成了负数;两负数相加,结果超出了范围,形式上变成了正数。
结果:
(1)原码:在数值前直接加一符号位的表示法。
[+7]原= 0 0000111 B[-7]原= 1 0000111 B
注意:a. 数0的原码有两种形式:
[+0]原=00000000B [-0]原=10000000B
8位二进制原码的表示范围:-127~+127
(2)反码:
正数:正数的反码与原码相同。
负数:负数的反码,符号位为“1”,数值部分按位取反。
例如: 符号位 数值位
[+7]反= 0 0000111 B
[-7]反= 1 1111000 B
注意:a. 数0的反码也有两种形式,即
[+0]反=00000000B
[- 0]反=11111111B
8位二进制反码的表示范围:-127~+127
(3)补码:
在计算机系统中,数值一律用补码来表示(存储)。
主要原因:使用补码,可以将符号位和其它位统一处理;同时,减法也可按加法来处理。另外,两个用补
码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃。
数值的补码表示也分两种情况:
正数:正数的补码和原码相同。
负数:负数的补码则是符号位为“1”,数值部分按位取反后再在末位(最低位)加1。也就是“反码+1”。
[+7]补= 0 0000111 B
[-7]补= 1 1111001 B
2 、已知一个数的补码,求原码的操作分两种情况:
(1)如果补码的符号位为“0”,表示是一个正数,所以补码就是该数的原码。
(2)如果补码的符号位为“1”,表示是一个负数。按照求负数补码的逆过程,数值部分应是最低位减1,然后取反。但是对二进制数来说,先减1后取反和先取反后加1得到的结果是一样的,故仍可采用取反加1 。
例:已知某数X的补码11101110B,试求其原码。
解:由[X]补=11101110B知,X为负数。求其原码表示时,符号位不变,数值部分按位求反,再在末位加1。
1 1 1 0 1 1 1 0 补码
1 0 0 1 0 0 0 1 符号位不变,数值位取反
1 +1
1 0 0 1 0 0 1 0 原码
若字长为8位,则补码所表示的范围为-128~+127。这是一个规定, 10000000这个补码表示的这个数是-128。所以n位补码能表示的范围是-2^(n-1)到2^(n-1)-1,比n位原码能表示的数多一个。
byte类型的范围:(负数最小值,1既是符号位又是值位)
Dec: -128 -1 0 127
Bin: 1000 0000 1111 1111 0000 0000 0111 1111
32位Int类型范围:
Dec: -2147483648 -1 0 2147483647
Hex: 0x80000000 0xFFFFFFFF 0x00000000 0x7FFFFFFF
3、溢出
两个有符号数进行加法运算时,如果运算结果超出可表示的有符号数的范围时,就会发生溢出,使计算结果出错。很显然,溢出只能出现在两个同符号数相加或两个异符号数相减的情况下。
对于加法运算,如果次高位(数值部分最高位)形成进位加入最高位,而最高位(符号位)相加(包括次高位的进位)却没有进位输出时,或者反过来,次高位没有进位加入最高位,但最高位却有进位输出时,都将发生溢出。因为这两种情况是:两个正数相加,结果超出了范围,形式上变成了负数;两负数相加,结果超出了范围,形式上变成了正数。
而对于减法运算,当次高位不需从最高位借位,但最高位却需借位(正数减负数,差超出范围),或者反过来,次高位需从最高位借位,但最高位不需借位(负数减正数,差超出范围),也会出现溢出。
#include <iostream>
#include <cstring>
using namespace std;
int main(){
int a = 0x7fffffff;
int b = 1;
printf("%x\n", a);
printf("%d\n", a);
printf("%x\n", a + 1);
printf("%d\n", a + 1);
system("PAUSE");
return 0;
}
结果:
7fffffff
2147483647
80000000
-2147483648