之前做项目的时候使用位操作不是很多,今天在刷leetcode上题目的时候用到了位操作,是leetcode中的第29题。
一、java的位操作:
位运算表达式由操作数和位运算符组成,实现对整数类型的二进制数进行位运算。位运算符可以分为逻辑运算符(包括~、&、|和^)及移位运算符(包括>>、<<和>>>)。
1)左移位运算符(<<)能将运算符左边的运算对象向左移动运算符右侧指定的位数(在低位补0)。左移一位(在不溢出的情况下)相当于乘以2。
2)“有符号”右移位运算符(>>)则将运算符左边的运算对象向右移动运算符右侧指定的位数。 “有符号”右移位运算符使用了“符号扩展”:若值为正,则在高位插入0;若值为负,则在高位插入1。右移一位相当于除以2。
3)Java也添加了一种“无符号”右移位运算符(>>>),它使用了“零扩展”:无论正负,都在高位插入0。
4)若对char,byte或者short进行移位处理,那么在移位进行之前,它们会自动转换成一个int。 只有右侧的5个低位才会用到。这样可防止我们在一个int数里移动不切实际的位数。 若对一个long值进行处理,最后得到的结果也是long。在leetcode这道题目里面需要用到的类型是long。
5)在这6种操作符,只有~取反是单目操作符,其它5种都是双目操作符。
二、java位操作的实际操作:
我们从其他博客里面看到的位操作的举例往往都是给一个数字,然后通过syso进行输出操作。
程序:public class PlusRightMoving{ public static void main(String[] args){ System.out.println("5>>1="+(5>>1)); }}输出结果:5>>1=2
但是需要注意的是,如果进行赋值操作和C/C++中是不一样的。
在C/C++中进行左移和右移操作:
div << 1;res << 1;
但是在java中进行位移操作需要配合赋值操作:
long div = 1;long res = 1;while(div < dived){ div = div << 1; res = res << 1;} if(div != dived){ div = div >> 1; res = res >> 1;}
如果只是像C/C++中进行操作一样,会不能编译通过。
三、位操作的一些应用题:
1)判断奇偶
只要根据最未位是0还是1来决定,为0就是偶数,为1就是奇数。因此可以用if ((a & 1) == 0)代替if (a % 2 == 0)来判断a是不是偶数。下面程序将输出0到100之间的所有偶数。
2)交换两数
int c = 1, d = 2;
c ^= d; d ^= c; c ^= d; System.out.println(“c=” + c); System.out.println(“d=” + d);3)变换符号
如对于-11和11,可以通过下面的变换方法将-11变成11
1111 0101(二进制) –取反-> 0000 1010(二进制) –加1-> 0000 1011(二进制)
同样可以这样的将11变成-11
0000 1011(二进制) –取反-> 0000 0100(二进制) –加1-> 1111 0101(二进制)
其他的应用可以参考博客文章:
其中有很多对java位操作的应用介绍。