Java数据结构和算法:位运算
位运算因为是CPU直接支持的操作指令,也是基于二进制的操作,所以具有相当高的效率,在一些场合,合理应用位运算将具有很高的性能。通常在一些加密算法,图型算法中都会使用到位运算。
移位运算符
| << | 左移运算符,将运算符左边的对象向左移动运算符右边指定的位数(在低位补0) | x<<3 |
| >> | “有符号”右移运算 符,将运算符左边的对象向右移动运算符右边指定的位数。使用符号扩展机制,也就是说,如果值为正,则在高位补0,如果值为负,则在高位补1. | x>>3 |
| >>> | “无符号”右移运算 符,将运算符左边的对象向右移动运算符右边指定的位数。采用0扩展机制,也就是说,无论值的正负,都在高位补0. | x>>>3 |
对于java移位运算的总结
对于左移运算,每左移一个位,高阶位都被移出(并且丢弃),并用0填充右边。这意味着当左移的运算数是int 类型时,每移动1位,它的第31位就要被移出并且丢弃;当左移的运算数是long 类型时,每移动1位它的第63位就要被移出并且丢弃。
左移都可以使原来的操作数翻倍,程序员们经常使用这个办法来进行快速的2 的乘法。但是你要小心,如果你将1移进高阶位(31或63位),那么该值将变为负值。
在对byte 和short类型的值进行移位运算时 , Java将自动把这些类型扩大为 int 型,而且,移位后的值也是int 型;如果左移不超过31位,原来对应各位的值不会丢弃。但是,如果你对一个负的byte 或者short类型的值进行移位运算,它被扩大为int 型后,它的符号也被扩展,结果的高位就会被1填充。因此,为了得到正确的结果,你就要舍弃得到结果的高位。这样做的最简单办法是将移位运算的结果再转换成byte 型 。
每右移一次,就相当于将该值除以2并且舍弃了余数。你可以利用这个特点将一个整数进行快速的2的除法。当然,你一定要确保你不会将该数原有的任何一位移出。
无符号右移(>>>)与右移的区别:
每一次右移,>>运算符总是自动地用它的先前最高位的内容补它的最高位。这样做保留了原值的符号
无符号移动总是在高位(最左边)补0。
与C、C++不同,Java中没有无符号型整数,而且明确规定了整型和浮点型数据所占的内存字节数,这样就保证了安全性、鲁棒性和平台无关性。
roundUpToPowerOfTwo(int i)
获取大于等于 某个整数 并且是 2 的幂数的整数
public static int roundUpToPowerOfTwo(int i) {i--; // If input is a power of two, shift its high-order bit right.// "Smear" the high-order bit all the way to the right.i |= i >>> 1;i |= i >>> 2;i |= i >>> 4;i |= i >>> 8;i |= i >>> 16;return i + 1; }可以看到这个算法进行了 5 次移位操作,乍一看,一脸懵逼,这是在干嘛?
细细一想啊,我现在要获取一个是 2 的幂数的整数,那其二进制的表现形式就是其最高位为1 ,低位全部为 0;或者其低位全部为 1,只需再对其加 1,即可变成 2 的倍数。
举个例子:
1000 0000
0100 0000 // 无符号右移一位
1100 0000 // 上面两个执行或操作的结果
1100 0000
0011 0000 // 无符号右移二位
1111 0000 // 上面两个执行或操作的结果
1111 0000
0000 1111 // 无符号右移三位
1111 1111 // 上面两个执行或操作的结果
其实我们只需将我们的关注点放置其元素为1的最高位上,执行右移操作,紧接着是或操作,最后的结果就是将高位的1,向后涂抹 (smear),全部变为1。
移位5次的原因在于 Java 中的整数是32位的,正好是2的 5次方。
算法刚开始的减一操作,则是为了防止刚开始传入的数字便是 2 的幂数。用来保证最终的结果是大于等于传入的参数的值。
总结
以上是生活随笔为你收集整理的Java数据结构和算法:位运算的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 详细介绍Java和C++区别
- 下一篇: RxJava 教程第一部分:为何使用Rx