计算机中的整数有三种表示方法 ——> 原码、反码、补码。
这三种表示方法均有符号位和数值位两部分,符号位是二进制最左边的数, 0 表示正,1 表示负,其他的是数值位。
正整数:
原码、反码、补码相同。
负整数:
原码 — 直接将二进制按照正负数的形式翻译成二进制就可以了。
反码 — 将原码的符号位不变,其他位依次按位取反(0取1、1取0)
补码 — 反码 +1 就是补码。
整型数据存放在内存中存放的是补码。
例如:
int a = 2;
//
// int 是占4个字节,一个字节8个比特位,一共32个比特位
// 所以2的二进制数是:(因为2位正整数,所以原、反、补码相同)
// 00000000000000000000000000000010 —— 原码
// 00000000000000000000000000000010 —— 反码
// 00000000000000000000000000000010 —— 补码
int b = -3;
//
// -3是负整数,二进制数是:
// 10000000000000000000000000000011 —— 原码
// 11111111111111111111111111111100 —— 反码(原码取反,符号位不变)
// 11111111111111111111111111111101 —— 补码(反码+1)
//
// 我们可以看一下在内存中的存储是什么(那就把-3的补码翻译成16进制)
// 1111 1111 1111 1111 1111 1111 1111 1101 —— 补码 (4个二进制位转化成一个16进制位)
// 15 15 15 15 15 15 15 13 —— 10进制
// f f f f f f f d —— 16进制 0xfffffffd
//
// 二进制位地位到高位的权值是2的0次方、2的1次方....以此类推.但是我们分成4个二进制位转16进制位。
// 比如 1111 从低位到高位(右到左) 1*2的0次+1*2的1次+1*2的2次+1*2的3次=15
// 在因为16进制是从 0——f,比如十进制的28转16进制是 1c
我们来看一下内存中的-3是不是 0xff ff ff fd ?
我们可以看到 b 里面放的就是 0xff ff ff fd
那数据为什么在内存中存放的是补码?
因在计算机系统中,数值一律用补码来表示和存储,原因在于,使用补码,可以将符号位和数值统一处理。
同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
举个例子吧:
比如我们算 1-1
但是CPU只有加法器,它会把减、乘、除法运算转换成加法运算。
1-1 ==> 1+(-1) 乘法、除法同减法转换类似
先用原码算一下
00000000000000000000000000000001 ——> 1的原码
10000000000000000000000000000001 ——> -1的原码
10000000000000000000000000000010 ——> 1+(-1)==> -2吗?错了,1-1是0啊
补码计算
00000000000000000000000000000001 ——> 1的原码(因为是正整数,所以原、反、补码相同)
10000000000000000000000000000001 ——> -1的原码
11111111111111111111111111111110 ——> -1的反码(符号位不变,其它位取反)
11111111111111111111111111111111 ——> -1的补码(反码+1)
00000000000000000000000000000001 ——> 1的原码
11111111111111111111111111111111 ——> -1的补码
100000000000000000000000000000000 ——> 1+(-1) 最左边多出了一位就丢掉了,只保留后面全0(高位丢掉,留下低位)
下来我们我们分析一下类型的取值范围,比如char、float、int 等等....
我用char来举例吧(有符号的char)
(二进制转十进制的算法跟上面一样,权值*那个位上的数字)
那无符号char是多少呢?
那char的范围出来了,float、int等等存储范围的算法同char。