目录
规则总结:
* ① 二进制的最高位是符号位:0正1负
* ② 正数的原码、反码、补码都一样(三码合一)
* ③ 负数的反码 = 原码的符号位不变,其他位取反(0->1、1->0)
* ④ 负数的补码 = 负数的反码 + 1 ,负数的反码 = 负数的补码 - 1
* ⑤ 0 的反码、补码都是 0
*
* ⑥ java都是带符号运算,所以 最高位是0就是正、最高位是1就是负
* ⑦ 计算机运算都是 以补码的方式进行运算的
* ⑧ 我们看到的结果都是原码
*
* >>、<< 和 >>> 的规则:
* ① 算数右移 >> :低位溢出,符号位不变,并用符号位补溢出的高位
* ② 算数左移 << :符号位不变,低位补0
* ③ >>> 逻辑右移:也叫无符号右移,低位溢出,高位补0
* ④ 没有 <<< !!!
*
* 补充个模的公式: a % b = a - (int)a/b *b
* 注意:有小数运算,等得的结果是近似值(对结果进行==判断时,要小心注意)
* -10.5 % 3 = -10.5 - (-10)/3*3 = -10.5 - (-9) = -1.5
举例说明(含推导)
1. ~、&、|、^ 部分
// 例题一:~2 = ? 按位取反
// 2 的原码(2进制)= 反码 = 补码: 0000 0000 0000 0010
// 取反(=补码),因为是负数,所以要继续转 : 1111 1111 1111 1101
// 转反码(-1): 1111 1111 1111 1100
// 转回到原码 : 1000 0000 0000 0011
System.out.println(~2); //-3
// 例题二:2&3 = ? 2按位与3
// 2的原码 = 反码 = 补码: 0000 0000 0000 0010
// 3的原码 = 反码 = 补码: 0000 0000 0000 0011
// 2的补码 & 3的补码 = 补码(正数:三码合一) = 原码 0000 0000 0000 0010
System.out.println(2&3); //2
//例题三:2|3 = ? 2按位或3
// 2的原码 = 反码 = 补码: 0000 0000 0000 0010
// 3的原码 = 反码 = 补码: 0000 0000 0000 0011
// 2的补码 | 3的补码 = 补码(正数:三码合一) = 原码 0000 0000 0000 0011
System.out.println(2|3); //3
//例题四:~-5 = ? 按位取反
// -5 的原码(2进制): 1000 0000 0000 0101
// -5 的反码(2进制): 1111 1111 1111 1010
// -5 的补码(-1): 1111 1111 1111 1011
// 取反(=补码),因为是负数,所以要继续转 : 0000 0000 0000 0100
System.out.println(~-5); //4
//例题五:13&7 = ? 13按位与7
// 13的原码 = 反码 = 补码: 0000 0000 0000 1101
// 7的原码 = 反码 = 补码: 0000 0000 0000 0111
// 13的补码 & 7的补码 =补码(正数:三码合一) = 原码 0000 0000 0000 0101
System.out.println(13&7); //5
//例题六:5|4 = ? 5按位或4
// 5的原码 = 反码 = 补码: 0000 0000 0000 0101
// 4的原码 = 反码 = 补码: 0000 0000 0000 0100
// 13的补码 | 7的补码 =补码(正数:三码合一) = 原码 0000 0000 0000 0101
System.out.println(5|4); //5
//例题七:-3^3 = ? -3按位异或3
// -3的原码: 10000000 00000000 00000000 00000011
// -3的反码: 11111111 11111111 11111111 11111100
// -3的补码(+1) 11111111 11111111 11111111 11111101
// 3的原码 = 反码 = 补码 00000000 00000000 00000000 00000011
// -3的补码 ^ 3的补码 11111111 11111111 11111111 11111110
// 转反码(-1) 11111111 11111111 11111111 11111101
// 转原码(结果): 10000000 00000000 00000000 00000010
System.out.println(-3^3); //-2
2. >> 、<< 、>>> 部分(注意没有<<<)
//例题八:1>>2
//1的原码 = 反码 = 补码: 00000000 00000000 00000000 00000001
//右移2位 00000000 00000000 00000000 00000000
System.out.println(1>>2); //0
//例题九:-1>>2
//1的原码: 10000000 00000000 00000000 00000001
//反码: 11111111 11111111 11111111 11111110
//补码(+1): 11111111 11111111 11111111 11111111
//右移2位(补码): 11111111 11111111 11111111 11111111
//转反码(-1): 11111111 11111111 11111111 11111110
//转原码: 10000000 00000000 00000000 00000001
System.out.println(-1>>2); //-1
//例题十:1<<2
//1的原码 = 反码 = 补码: 00000000 00000000 00000000 00000001
//左移2位 00000000 00000000 00000000 00000100
System.out.println(1<<2); //4 1*2*2(快速算法)
//例题十一:-1<<2
//1的原码: 10000000 00000000 00000000 00000001
//反码: 11111111 11111111 11111111 11111110
//补码(+1): 11111111 11111111 11111111 11111111
//左移2位 11111111 11111111 11111111 11111100
//转反码(-1): 11111111 11111111 11111111 11111011
//转原码: 10000000 00000000 00000000 00000100
System.out.println(-1<<2); //-4
//例题十二:3>>>1
//3的原码 = 反码 = 补码 : 00000000 00000000 00000000 00000011
//3无符号右移1: 00000000 00000000 00000000 00000001
System.out.println(3>>>1); //0
//例题十三:-3>>>1
//-3的原码: 10000000 00000000 00000000 00000011
//-3的反码: 11111111 11111111 11111111 11111100
//-3的补码(+1): 11111111 11111111 11111111 11111101
//-3的补码无符号右移1: 01111111 11111111 11111111 11111110
System.out.println(-3>>>1); //2,147,483,646
补充:快速算法
a<<b :相当于 a*2的b次方
a>>b :相当于 a*2的-b次方 (a/2/2/2... 除了b个 2)
//快速算法:
System.out.println(4<<3); // 4*2*2*2=32
System.out.println(16>>2); // 16/2/2 = 4