java位运算符

Java 语言中的位运算符分为位逻辑运算符位移运算符两类,下面详细介绍每类包含的运算符。

1. 位逻辑运算符

位逻辑运算符包含 4 个:&(与)|(或)~(非)^(异或)。除了 ~(即位取反)为单目运算符外,其余都为双目运算符。表 1 中列出了它们的基本用法。

运算符含义实例结果
&按位进行与运算(AND)4 & 54
|按位进行或运算(OR)4 | 55
^按位进行异或运算(XOR)4 ^ 51
~按位进行取反运算(NOT)~ 4-5

1.1 与运算符

位与运算符为 &,其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位同时为 1,那么结果才为 1,否则为 0。因此,任何数与 0 进行按位与运算,其结果都为 0。

应用:

判断奇偶性:任意数 a&1=0 为偶数,a&1=1为偶数

取低位:根据运算性质,任意数a&(1<<n)-1 得到a的低n位,代码举例如下:

    public static void main(String[] args) {
        System.err.println(Integer.toBinaryString(27)); //1011
        System.err.println(Integer.toBinaryString(11));// 11011
        System.err.println(11 & (1 << 3) - 1); //3  即011
        System.err.println(27 & (1 << 3) - 1); //3
        System.err.println(27 & (1 << 4) - 1); //11 即1101
    }

利用取低位的性质,得到另一个应用:任意数(0除外)a&(a-1)==0即表示a是2的次方数

取余a%(2^n) = a&(1<<n-1) 注意这里的^是幂函数,仅限于除数是2的次方数如a%16=a&15

1.2 或运算符

 位或运算符为 |,其运算规则是:参与运算的数字,低位对齐,高位不足的补零。如果对应的二进制位只要有一个为 1,那么结果就为 1如果对应的二进制位都为 0,结果才为 0。

应用:后位置1(利用的就是加粗部分的运算特性),如hashmap的tableSizeFor方法

1.3 异或运算符

位异或运算符为^,其运算规则是:参与运算的数字,低位对齐,高位不足的补零,如果对应的二进制位相同(同时为 0 或同时为 1)时,结果为 0;如果对应的二进制位不相同,结果则为 1。

特性:a ^ a = 0,a ^ 0 = a,(a ^ b) ^ c = a ^ (b ^ c)

应用:不使用临时变量,交换两个数的值

a ^= b;
b ^= a; 
a ^= b;
分析:对应这三步
a = a ^ b;
b = a ^ b = (a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a;
a = a ^ b = (a ^ b) ^ b = (a ^ a) ^ b = b ^ 0 = b

附,该题还有其他解法如:

a = a + b;
b = a - b;
a = a - b;

1.4 取反运算符

位取反运算符为~,其运算规则是:只对一个操作数进行运算,将操作数二进制中的 1 改为 0,0 改为 1。

应用:(这里涉及到负数补码的知识)

求相反数: ~a + 1

求绝对值: a >> 31 == 0 ? a : (~a + 1)

==================================================================

2. 位移运算符

参考文章负数位运算的右移操作-C语言基础 - 十一一个人 - 博客园

首先需要了解一下原码,反码,补码的知识:原码,补码,反码_Mr_moving-CSDN博客

在计算机中,数值一律用补码来表示(存储),无论是左移还是右移,都是以此为前提进行操作。

2.1 右移:

右移分为有符号右移和无符号右移(java中用>>>符号表示),区别仅在于有符号右移,符号位不移动保持不变,无符号右移,高位统一补0,所以负数会变正数

下面是有符号右移的例子

首先是 +5>>2 = 1

+5
原码 0000 …… 0101
补码 0000 …… 0101
>>2(正数右移高位补0
补码 0000 …… 0001
原码 0000 …… 0001
= 1




然后是 -5>>2 = -2

-5
原码 1000 …… 0101
反码 1111 …… 1010 负数的反码是保留符号位不变源码取反
补码 1111 …… 1011 补码是反码加1
>>2 (负数右移高位补1)
补码 1111 …… 1110
反码 1111 …… 1101 补码转反码减1
源码 1000 … 0010 负数反码转源码保留符号位不变取反

= -2

无符号右移

-5
原码 1000 …… 0101
反码 1111 …… 1010 负数的反码是保留符号位不变源码取反
补码 1111 …… 1011 补码是反码加1
>>>2(无符号右移,高位补0)
补码 0011 …… 1110
反码 (此时符号位已经变为0了,系统会当成正数来处理,原反补码均一样)
原码 0011 …… 1110
= 这个不好说,得看操作系统的位数(在我这里int为32位,
结果为:107374182==>00111111 11111111 11111111 11111110)

2.2 左移:

左移相对于右移来说,就十分朴实无华,不在乎符号位,也就不存在无符号左移的说法,因为左移就是在低位补0

无论是有符号的正数还是负数,其左移都是在其补码的基础上面左移,而且低位都是补0。看到这里,你是否就意识到了一个问题,“如果正数的补码在左移的过程中,刚好有一个1移到了最高位,那么是否就会变成了负数呢?”嗯,这种情况确实是会发生的。负数左移到一定值的时候也会变成正。

2.3 注意事项

1. 在移位运算时,byte、short和char类型移位后的结果会变成int类型,所以一般是以32位的补码形式运算。

2. 当移位较大时,比如移动33位,对于byte、short、char和int进行移位时,规定实际移动的次数是移动次数和32的余数,也就是移位33次和移位1次得到的结果相同。移动long型的数值时,规定实际移动的次数是移动次数和64的余数,也就是移动66次和移动2次得到的结果相同。

2.4 位移运算的应用

在计算机系统中通常是以补码的形式存在的,以16位int数据为例,其中最为特殊的就 -1的补码 , -1的补码为:1111 1111 1111 1111;通过-1>>>n可以获取(二进制)从低位到指定位n全部为1的值;同时使用-1<< m可以获取从指定位m到符号位全部为1的值;通过(-1>>>n)&(-1<< m)就可以获取二进制中指定位置(低位到高位)全部为1的int值。

==================================================================

附运算符优先级,没必要记,括号是万能的。

优先级运算符
1()、[]、{}
2!、+、-、~、++、--
3*、/、%
4+、-
5«、»、>>>
6<、<=、>、>=、instanceof
7==、!=
8&
9^
10|
11&&
12||
13?:
14=、+=、-=、*=、/=、&=、|=、^=、~=、«=、»=、>>>=

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值