原码补码反码
原创
©著作权归作者所有:来自51CTO博客作者qq63a17a25c2b1c的原创作品,请联系作者获取转载授权,否则将追究法律责任
1)存储1字节(8位)大小的数字(char)
原码(用户的角度):原始的二进制
1、用户的数字分为正负数,符号位的存储
2、最高位为符号位:0代表为正数,1代表为负数
3、1000 0000 左边是高位, 右边是低位
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: 0000 0000
-0: 1111 1111
反码存储导致1个问题:
1、0有两种存储方式
以反码来算:
1-1 = 1 + -1
1: 0000 0001
-1: 1111 1110
1111 1111 = -0
计算机存储数字以补码方式存储(为了解决负数的储存)
补码:
1、正数的原码、反码、补码都一样
2、补码为其反码+1
3、补码符号位不动,其它位求反,最后整个数+1,得到原码
1,+1: 0000 0001
-1: 1111 1111
+0: 0000 0000
-0:10000 0000 (最高位丢弃)= 0000 0000
以补码来算:
1-1 = 1 + -1
1: 0000 0001
-1: 1111 1111
10000 0000(最高位丢弃) = 0000 0000
10进制数,站在用户的角度,原码
二进制、八进制、十六进制数,站在计算机角度,补码
在计算机系统中,数值一律用补码来存储,主要原因:
1.统一了0的编码
2.将符号位和其他位统一处理
3.将减法运算转变为加法运算
4.两个用补码表示的数相加,如果最高位(符号位)有进位,则进位被舍弃
原码求补码:
1)最高位符号位,其它位就是二进制(原码)
2)在1)基础上,符号位不变,其它位取反
3)补码在2)基础上加1
补码求原码:
1)补码
2)求补码的反码,符号位不变,其它位取反
3)原码在2)基础上加1
例:
//一个字节
1000 0001
0x81
//二进制、八进制、十六进制数,站在计算机角度,补码
//0x81转化为二进制1000 0001,最高位为1,说明是负数
char a = ox81;
补码:1000 0001
反码:1111 1110
原码:1111 1111 = -127
//10进制数,站在用户的角度,原码
printf("%d\n", a); // -127
//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
%x: f f f f f f 8 5
//%x, 默认以4个字节(32bit)大小打印
//二进制、八进制、十六进制数,站在计算机角度,补码
printf("%x\n", a); // ffffff85
数据类型范围(站在10进制角度,原码)
char 1个字节(8位)
有符号范围:
正数:
0000 0000 ~ 0111 1111
0 ~ 127
负数:
1000 0000 ~ 1111 1111
-0 ~ -127
-0 当做 -128 使用
-128:
原码: 1 1000 0000
反码: 1 0111 1111
补码: 1 1000 0000
-128 ~ 127
无符号:
0000 0000 ~ 1111 1111
0 ~ 255
char:
有符号:-128 ~ 127
无符号: 0 ~ 255
赋值或则越算,记得不要越界:
char ch = 127 + 2;
/*
129:
补码:1000 0001
反码:1111 1110
原码:1111 1111
*/4[
printf("%d\n", ch); // -127
unsigned char b = 255 + 2;
//257转化为二进制 0001 0000 0001 (只取8位)0000 0001 --> 1
printf("%u\n", b); // 1