原码 反码 补码 (为什么计算机存储数字以补码方式存储)
1)存储1字节(8位)大小的数字(char)
原码(用户角度):原始的二进制
1、用户的数字分为正负数,符号位的存储
2、最高位为符号位:0代表为正数,1代表为负数
3、1000 0001 左边是最高位,右边是最低位
1, +1: 0000 0001
-1: 1000 0001
+0:0000 0000
-0: 1000 0000
原码导致存储2个问题:
1、0有两种存储方式
2、正数和负数相加,结果不正确(计算机只会加不会减)
1-1 =1+ -1
1: 0000 0001
-1:1000 0001
1000 0010 = -2
反码(为了算补码):
1、正数的原码和反码都是一样的
2、求原码
3、符号位不变,其他位取反(0为1,1变0)
1,+1: 0000 0001
-1: 1111 1110
+0: 0111 1111
-0: 1111 1111
反码存储导致1个问题
1、0有两种存储方式
1-1 = 1 + -1
1: 0000 0001
-1: 1111 1110
1111 1111 = -0 (反码)
为什么计算机的存储方式要以补码方式存储(为了解决负数的存储)
补码:
1、正数的原码、反码、补码都一样
2、补码为其反码+1
1, +1: 0000 0001
-1: 1111 1111
+0: 0000 0000
-0: 10000 0000(最高位丢弃)= 0000 0000
这里很好地印证了,补码解决了负数的存储方式
以补码方式来算:
1-1: 1+ -1
1: 0000 0000
-1: 1111 1111
10000 0000 (最高位丢弃) = 0000 0000
10进制,站在用户的角度,原码
二进制、八进制、十六进制,站在计算机角度,补码
验证补码
//1个字节
1000 0001
81
原码求补码:
1)最高位符号位,其它位就是二进制(原码)
2)在1)基础上,符号位不变,其它位取反
3)补码在2)基础上加1
补码求原码:
1)补码
2)求补码的反码,符号位不变,其它位取反
3)原码再2)基础上加1
//二进制、八进制、十六进制,站在计算机角度,补码
//0x81转为为二进制位1000 0001,最高位为1,说明是负数
char a = 0x81;
补码:1000 0001
反码:1111 1110
原码:1111 1111 = -127
//10进制数,站在用户的角度,原码
printf("%d\n", a); //-127
//二进制、八进制、十六进制,站在计算机角度,补码
//0xe5二进制为1110 0101,最高位为1,说明是负数,它是负数的补码
char b = 0xe5;
补码:1110 0101
反码:1001 1010
原码:1001 1011 = -27
//10进制数,站在用户的角度,原码
printf("%d\n", b);
0x6f的二级制为0110 1111,最高位为0,它是正数**(注意这里是正数,正数的原码、反码、补码都是一样的)**
char c = 0x6f;
printf("%d\n", c);
//10进制数,站在用户的角度,原码
int a = -123;
原码:1000 0000 0000 0000 0000 0000 0111 1011
反码:1111 1111 1111 1111 1111 1111 1000 0100
补码:1111 1111 1111 1111 1111 1111 1000 0101
f f f f f f 8 5
%x,默认以4个字节(32位)大小打印
//二进制、八进制、十六进制,站在计算机角度,补码
printf("%x\n", a);
char a=0x80
补码: 1000 0000
反码: 1111 1111
原码:10000 0000