个人理解,仅供参考。
机器数和真值
1.机器数
一个数在计算机中的二进制表示形式,叫做这个数的机器数。机器数是带符号位的,在计算机中用一个数的最高位存放符号位,正数为0,负数为1。
@Test
public void test() {
int a = 5;
int b = -5;
System.out.println("5对应的二进制数:" + Integer.toBinaryString(a));
System.out.println("-5对应的二进制数:" + Integer.toBinaryString(b));
}
PS:5对应的二进制数应该是 00000000 00000000 00000000 00000101
2.真值
由于第一位是符号位,所以机器数的形式值就不等于真正的数值。例如上面的二进制数,呃,太长算不了。
为了方便计算,我们假设计算机字长为8位,所以:
+5 ---- 0000 0101
-5 ---- 1111 1011
假设不考虑符号位 那么1111 1011计算出来的结果是251。为了区别将带符号位的机器数对应的真正数值称为机器数的真值。
原码 反码 补码
1.正码
原码就是符号位位加上真值得绝对值,第一位使用符号位,其余位表示数值。例如8bit二进制:
[+1]原 = 0000 0001
[-1]原 = 1000 0001
取值范围为[1111 1111,0111 1111] 即 [-127,127]
2.反码
正数的反码是其本身。
负数的反码就是其原码的基础上,符号位不变,其余的位取反。
[+1] = [0000 0001]原 = [0000 0001]反
[-1] = [1000 0001]原 = [1111 1110]反
3.补码
正数的补码还是它自己。
负数的补码是在其原码的基础上,符号位不变,其余各位取反。或者说在其反码的基础上+1。
[+1] = [0000 0001]原 = [0000 0001]反 = [0000 0001]补
[-1] = [1000 0001]原 = [1111 1110]反 = [1111 1111]补
为何使用原码 反码 补码
运算法则:减去一个正数等于加上一个负数。
那么问题来了:
1.计算十进制的表达式:1 - 1 = 0
1 - 1 = 1 + (-1)
= [0000 0001]原 + [1000 0001]原
= [1000 0000]原 = -2
错误的结果。。。
2.使用反码
1 - 1 = 1 + (-1)
= [0000 0001]原 + [1000 0001]原
= [0000 0001]反 + [1111 1110]反
= [1111 1111]反
= [1000 0000]原 = -0
[1000 0000]原 ---- -0
[0000 0000]原 ---- +0
3.使用补码
1 - 1 = 1 + (-1)
= [0000 0001]原 + [1000 0001]原
= [0000 0001]补 + [1111 1111]补
= [0000 0000]补
(-1) + (-127) = [1000 0001]原 + [1111 1111]原
= [1111 1111]补 + [1000 0001]补
= [1000 0000]补
-128的补码[1000 0000]补,也就是使用-0的补码表示。但是-128并没有原码和反码。
对[1000 0000]补求其原码得出 [0000 0000]原是错误的。
解决0的符号问题。
移位运算符 >> >>> <<
1.>> 带符号右移
将二进制向右移动n位,在丢失的位置补上符号位
2.>>> 无符号右移
将二进制向右移动n位,在丢失的位上补上0
3.<< 左移
将二进制向左移动n位,在丢失的位上补上0
@Test
public void test() {
int a = 15;
int b = -15;
System.out.println(Integer.toBinaryString(a)) ;
System.out.println("5 >> 3 :" + Integer.toBinaryString(a >> 3));
System.out.println("5 >>> 3 :" + Integer.toBinaryString(a >>> 3));
System.out.println("5 << 3 :" + Integer.toBinaryString(a << 3));
System.out.println(Integer.toBinaryString(b)) ;
System.out.println("-5 >> 3 :" + Integer.toBinaryString(b >> 3));
System.out.println("-5 >> 3 :" + Integer.toBinaryString(b >>> 3));
System.out.println("-5 >> 3 :" + Integer.toBinaryString(b << 3));</span>
}
位运算符 & | ^ ~
& 全1才1
~ 按位取反
| 有1就1
^ 相同为0 不同为1
@Test
public void test() {
int a = 15;
int b = -15;
System.out.println(Integer.toBinaryString(a)) ;
System.out.println(Integer.toBinaryString(b)) ;
System.out.println("a | b :" + Integer.toBinaryString(a | b));
System.out.println("a & b :" + Integer.toBinaryString(a & b));
System.out.println("a ^ b :" + Integer.toBinaryString(a ^ b));
System.out.println("~a :" + Integer.toBinaryString(~a));
}
PS:
1.一个数的补码的补码是其原码。
2.一个数异或一个数两次还是等于它本身。 a^b^b = a