(最近刚来到简书平台,以前在CSDN上写的一些东西,也在逐渐的移到这儿来,有些篇幅是很早的时候写下的,因此可能会看到一些内容杂乱的文章,对此深感抱歉,以下为正文)
引子
位移运算符以前一直没怎么注意,今天因为某些原因使用了一下,结果跟预期不一样,所以回头看了一下,最终发现在使用的时候还是有一些注意事项的。
正文
Java中提供了3个位移运算符:
- 带符号的右移运算符(>>):将运算符左边的运算对象向右移动运算符右侧指定的位数。“有符号”右移位运算符使用了“符号扩展”:若值为正,则在高位插入 0;若值为负,则在高位插入 1 。
- 带符号的左移运算符(<<):将运算符左边的运算对象向左移动运算符右侧指定的位数(在低位补 0) 。
- 不带符号的右移运算符(>>>):将运算符左边的运算对象向右移动运算符右侧指定的位数。它使用了“零扩展”:无论正负,都在高位插入0 。
我个人是有点儿奇怪为什么没有不带符号的左移运算符呢0-0
首先要明确一点的是,位移运算符进行运算的时候,针对的是数字的补码,这点首先要搞清楚,刚开始我一直在用原码进行推算,所以结果一直出错,表示非常尴尬。如果你不知道原码,补码,反码的概念,可能你需要查找一下相关的资料了解一下,这里就不再多做说明了。
package test;
public class Test {
public static void main(String[] args) {
//11111111 11111111 11111111 11111111 -1补码
int i = -1;
//00000000 00111111 11111111 11111111 无符号右移10位后的补码
i >>>= 10;
//4194303
System.out.println("-1(int) >>> 10 : "+i);
//11111111 11111111 11111111 11111111 111111111 11111111 11111111 11111111
long l = -1;
//00000000 00111111 11111111 11111111 111111111 11111111 11111111 11111111
l >>>= 10;
//18014398509481983
System.out.println("-1(long) >>> 10 : "+l);
//short,char,byte进行位运算时都会先转换成int型,刚开始不知道这点,纠结了好久。
//11111111 11111111 11111111 11111111
short s = -1;
//00000000 00000000 01111111 11111111
s >>>= 17;
//32767
System.out.println("-1(short) >>> 17 : "+s);
//11111111 11111111 11111111 11111111
byte b = -1;
//11111111 11111111 11111111 11111111
b >>= 26;
//-1
System.out.println("-1(byte) >> 26 : "+b);
}
}
综上,有几点需要注意:
- 位运算是针对数值的补码来进行的。
- short,char,byte进行位运算时,需要先将其转换成对应的int型再进行运算。
- 当需要移动的位数超过数据类型的位数时,将跟数据类型的位数限制进行取模运算,得到的结果才是真正需要移动的位数。
下面有个通过位移符来实现的输出一个int数值的二进制的方法,可以加深一下学习:
public void printBinInt(String s, int i) {
System.out.println(s + ", int: " + i + ", binary: ");
System.out.print(" ");
//通过循环,用1与数字的每一位相与,从而得出当前位的值是0还是1
for(int j = 31; j >=0; j--){
if(((1 << j) & i) != 0)
System.out.print("1");
else
System.out.print("0");
}
System.out.println();
}
以上为本篇的全部内容。
网友评论