补码互补对称:
案例
public class Demo04 { public static void main(String[] args) { /* * 测试补码的互补对称现象: -n = ~n+1 min除外 * ~ 取反计算:将2进制每个位进行翻转 1变0,0变1 */ int n = 20; int m = ~n + 1; //m为n的相反数 -20 System.out.println(m); //分析运算过程: System.out.println(Integer.toBinaryString(n)); System.out.println(Integer.toBinaryString(~n)); System.out.println(Integer.toBinaryString(~n+1)); /* n = 00000000000000000000000000010100 16+4 = 20 ~n = 11111111111111111111111111101011 -1-4-16=-21 ~n+1= 11111111111111111111111111101100 -1-1-2-16=-20 */ } }
int类型的编码:
经典面试题目:
System.out.println(~80+1);
1
上述代码的输出结果:( B ) A.-79 B.-80 C.-81 D.-82
System.out.println(~-80+1);
1
上述代码的输出结果:( B ) A.79 B.80 C.81 D.82
System.out.println(~80);
1
上述代码的输出结果:( C ) A.-79 B.-80 C.-81 D.-82
4 二进制运算符
常见运算符
取反 ~
与运算 &
或 |
右移位 >>>
数学又移位 >>
左移位 <<
与运算 & (逻辑乘法)
基本运算规则:有0则0
0 & 0 -> 0
0 & 1 -> 0
1 & 0 -> 0
1 & 1 -> 1
运算时候讲两个数字对齐位数,对应位进行与计算。
举个例子:
7 7 d d d e 7 d
n = 01110111 11011101 11011110 01111101
m = 00000000 00000000 00000000 11111111 mask 掩码
k=n&m 00000000 00000000 00000000 01111101
如上代码的运算意义:n的最后8位数被截取下来,存储到了k中,经常用于截取数据部分位计算,这种计算称为“掩码(Mask)运算”。 其中m称为“掩码”,按照1的个数是8个称为8位掩码。
代码案例:
int n = 0x77ddde7d;
int m = 0xff;
int k = n & m;
System.out.println(Integer.toBinaryString(n));
System.out.println(Integer.toBinaryString(m));
System.out.println(Integer.toBinaryString(k));
>>> 右移位计算
运算规则:将2进制数整体向右移动,低位自动溢出舍弃,高位补0。
举个例子:
n = 01101111 11101111 00110111 10110111
n>>>1 = 001101111 11101111 00110111 1011011
n>>>2 = 0001101111 11101111 00110111 101101
n>>>8 = 00000000 01101111 11101111 00110111
b3=(n>>>8) & 0xff;
00000000 00000000 00000000 00110111
代码:
int n = 0x6fef37b7;
int m = n>>>1;
int k = n>>>2;
int g = n>>>8;
int b1 = (n>>>24) & 0xff;
int b2 = (n>>>16) & 0xff;
int b3 = (n>>>8) & 0xff;
int b4 = (n>>>0) & 0xff;
//按照2进制输出 n m k g b3
//如何计算 b1 b2 b3 b4 ?
将一个整数拆分为4个字节
b1 b2 b3 b4
n = 01110111 11011101 11011110 01111101
b1 = 00000000 00000000 00000000 01110111
b2 = 00000000 00000000 00000000 11011101
b3 = 00000000 00000000 00000000 11011110
b4 = 00000000 00000000 00000000 01111101
案例:
int b1 = (n>>>24) & 0xff;
int b2 = (n>>>16) & 0xff;
int b3 = (n>>>8) & 0xff;
int b4 = (n>>>0) & 0xff;
| 或运算(逻辑加法)
基本规则:有1则1
0 | 0 -> 0
0 | 1 -> 1
1 | 0 -> 1
1 | 1 -> 1
将两个2进制数字对齐位数,对应位进行或运算。
举个例子:
n = 00000000 00000000 00000000 10110101
m = 00000000 00000000 10110111 00000000
k = n|m 00000000 00000000 10110111 10110101
如上案例的意义:n和m两个数进行拼接,k中低8位数是n,高8位数是m
案例:
int n = 0xb5;
int m = 0xb700;
int k = n | m;
//按照2进制检测 n m k
<< 左移位计算
将2进制数字的整体向左移动,高位自动溢出,低位补0;
举个例子:
n = 10111011 10101110 10000011 11010001
m = n<<1 0111011 10101110 10000011 110100010
k = n<<2 111011 10101110 10000011 1101000100
g = n<<8 10101110 10000011 11010001 00000000
代码:
int n = 0xbbae83d1
int m = n<<1;
int k = n<<2;
int g = n<<8;
//按照2进制输出 n m k g
将4个字节数据合并为一个int整数:
b1 = 00000000 00000000 00000000 01110111
b2 = 00000000 00000000 00000000 11011101
b3 = 00000000 00000000 00000000 11011110
b4 = 00000000 00000000 00000000 01111101
b1<<24 = 01110111 00000000 00000000 00000000
b2<<16 = 00000000 11011101 00000000 00000000
b3<<8 = 00000000 00000000 11011110 00000000
b4 = 00000000 00000000 00000000 01111101
合并:n = (b1<<24)|(b2<<16)|(b3<<8)|b4
b1 b2 b3 b4
n = 01110111 11011101 11011110 01111101
代码:
int b1 = 0x77;
int b2 = 0xdd;
int b3 = 0xde;
int b4 = 0x7d;
int n = (b1<<24)|(b2<<16)|(b3<<8)|b4;
//按照2进制检测 b1 b2 b3 b4 n
移位计算的数学意义 和 >>
2进制中,数字整体向左移动一次扩大2倍(溢出情况除外)
举个例子:
n = 00000000 00000000 00000000 00000110 6
m = n<<1 0000000 00000000 00000000 000001100 12
k = n<<2 000000 00000000 00000000 0000011000 24
...
经典面试题目:
表达式 n * 8 可以替换为( n<<3 ) (被乘数是2的整次幂)
>> 称为数学右移位计算,运算结果相当于数学除法(溢出时候向小方向取整数)
>>移位时候: 正数高位补0,负数高位补1
>>> 移位时候:无论正负,高位都补0
举个例子(负数)
n = 11111111 11111111 11111111 10011100 -1-1-2-32-64 -100
m =n>>1 111111111 11111111 11111111 1001110 -1-1-16-32 -50
k =n>>2 1111111111 11111111 11111111 100111 -1-8-16 -25
g =n>>3 11111111111 11111111 11111111 10011 -1-4-8 -13
f =n>>>1 011111111 11111111 11111111 1001110 正数
>>>逻辑右移位计算,不管符号,将数字整体向右移动
>> 数学右移位计算,有符号移位,符合数学计算结果
如果为了替代数学计算就使用 >>
如果为了数字整体向右移动,不考虑数学结果,就使用 >>>
经典面试题目:
表达式 n / 8 (n>0)可以替换为( n>>3 ) (除数是2的整次幂)