位运算
在Java代码中一个数看起来是十进制,其实底层都是 二进制的数 。
int 整形是 32位的 二进制数。 Long 类型是64位的。
打印一个 int 整形数字, 32位的二进制数如下 :
public static void main(String[] args) {
int a = 3;
print(a);
}
public static void print(int num ){
for(int i =31 ; i >= 0 ; i--){
// 1 左移 i 位
System.out.print((num & (1 << i )) == 0 ? "0" : "1");
}
System.out.println();
}
结果:
00000000000000000000000000000011
1:00000000000000000000000000000001
2:00000000000000000000000000000010
3: 00000000000000000000000000000011
4: 00000000000000000000000000000100
这就是一个32位的二进制数,
从 0 ~ 31 位。从右侧开始是0,到最左侧是第31位。分别对应 2⁰ ~ 2³¹ 。
如果该位置位1,则计算;为0,则不计算
首先解释下代码含义
& | 与 | 两个位都为1时,结果才为1 |
<< | 左移 | 各二进位全部左移若干位,高位丢弃,低位补0 |
for(int i =31 ; i >= 0 ; i--){
// 1 左移 i 位
System.out.print((num & (1 << i )) == 0 ? "0" : "1");
}
& 与 :
int 整形变量 num 是32位,循环32次和1的左移操作做【与】操作,1每次左移【i】位,如果两个位置都是1,那么就打印1,否则打印0 。
比如 要提取 num 2进制数的第6位,那就让 1 左移 6 位(1 << 6),与其做 与 , 如果是1 ,那就打印出1 .
左移:
各二进位全部左移若干位,高位丢弃,低位补0。
比如 【 13 】这个数字, 二进制是
// 数字 13 的二进制
00000000000000000000000000001101
// 13 <<3 左移 3 位,右侧补0 右侧补了3个0
00000000000000000000000001101000
如果数字太大,左移溢出了呢,那就丢弃
int c = 1322222222;
print(c);
print(c << 3);
打印结果: 左移3位, 高位丢弃
01001110110011111000001010001110
01110110011111000001010001110000
负数:
32位的二进制数字,最高位31位【0】代表是正数;【1】代表是负数。所以最大数就是 0 ~ 2 ³¹ -1 。
整形最大数字:
int max = Integer.MAX_VALUE;
System.out.println(max);
print(max);
打印结果:
2147483647
01111111111111111111111111111111
如何计算负数:
负数计算就是 正数取反加1;
int j = 9;
int j1 = -j;
int j2 = ~j + 1;
j1 和 j2 是一样的结果;值都是 -9
j2 就是 取反加1
负数: 符号(第31)位是 1, 后面的值取反(正的是0,那就取1;正的是1,那就取0),再加个1 。
- 举例如下: 数字【1】
// 1 的正数
00000000000000000000000000000001
// 1 的负数
11111111111111111111111111111111
首先最高位是符号位,1代表是负数,然后不管符号位了,剩下的正1的值取反,(正的是0,那就取1;正的是1,那就取0),
那这样结果就是 11111111111111111111111111111110 ,
最后再加个1 就是:
11111111111111111111111111111111 。
- 举例数字【13】
//13
00000000000000000000000000001101
//-13
11111111111111111111111111110011
<1>首先正13取反结果:
11111111111111111111111111110010 ,
<2>然后再加个1 ,结果:
11111111111111111111111111110011
取反 : ~
一个数字 N,相反数怎们求 ? 直接负号和 N取反加1是相同的结果,就是表示它的相反数。
取一个数的相反数,为何要 取反加1,就是可以在做运算的时候,底层走一套逻辑。不需要区分这个数是正数还是负数。
2
一个数,相反数怎们求 ?
int k = 9;
// 第一种方法:直接 ”-“ 负号
int p = -k;
// 第一种方法:取反加1; [~]符号就是取反的意思
p = ~k + 1;
System.out.println(p);
print(k);
print(p);
Console:
-9
00000000000000000000000000001001
11111111111111111111111111110111
十进制的 加减乘除,其实都是将十进制数翻译成二进制数,做
| 有一个是1 ,就可以是1
& 两个都是1,才是1
^ 相同为0,不同为1
~ 取反
这些位运算的。
右移 :
右移就是往右边移动 N 位,右移之后,左侧用谁来补?0,还是 1 ?,所以右移有两种方式分别是:
>> (带符号右移) :右移后,左侧空位用符号位来补;如果原来的数符号位是0,那就用0来补;如果原来的数是个负数,符号位是1,那就用1来补空位
>>>(不带符号右移):右移后,左侧空位不用符号位来补,直接用0来补
int j = 9;
print(j);
print(j >> 1);
结果如下:
00000000000000000000000000001001
00000000000000000000000000000100
使用负数右移举例:
int j = -965454646;
print(j);
print(j >> 1); //这是带符号右移
Console:
11000110011101000101010011001010
11100011001110100010101001100101
-- 可以看到,右移之后,用原来的符号1 ,来填补左边的空位
====================================================================
【不带符号右移】
j = -965454646;
print(j);
print(j >>> 1); // 不带符号右移
Console:
11000110011101000101010011001010
01100011001110100010101001100101