public class Test6
{
public static void main(String[] args)
{
//位运算符
// << 左移运算符
//5 的二进制是 0000 0101
//左移一位的话0000 1010
//5 左移一位是10,是不是相当于5*2
System.out.println(5 << 1);
//3左移一位正好是6
System.out.println(3 << 1);
//3左移两位是12,也就是*4
System.out.println(3 << 2);
//对比下,其实这个表达式跟上方的位移的结果
//是一致的,运算效率上却要慢很多,这里只是
//描述下,左移相当于乘上2的几次幂
System.out.println((int)(3 * Math.pow(2, 2)));
//下边发现左移0和32还是5,为什么呢?
System.out.println(5 << 0);
System.out.println(5 << 32);
//木哈哈,这个绝对大杀器,为什么-1是31,-2是30?
System.out.println(5 << -1);
System.out.println("====================================>");
//打印一下x的位移情况,发现左移32位,x还是
//原值,为什么会这样?
//分析下最后几行,发现,并不是逐位补位的,
//最后一行的像突然插进去的一样。
int x = 7;
for (int shift = 0; shift <= 32; shift++)
{
System.out.println(getIntegerToBinary(x << shift));
}
System.out.println("====================================>");
//到这里可以看见,貌似从32开始,又开始像0-31
//那样子逐位位移了,到第64次的时候又会在继续
//这看起来是不是像模运算呢?
//其实这不难理解,比如没有这个现象的话,咱就单
//说位移,32位之后就都是0了吧,显然没有意义,
//对于一个int的有效位移次数仅是0-31
System.out.println(getIntegerToBinary(x << 33));
System.out.println("====================================>");
//事实证明,猜想是对的,但问题是,真的是这样?
//模运算是很慢的,如果真是这样,位移操作还能比
//乘法快?
for (int shift = 0; shift <= 32; shift++)
{
System.out.println(getIntegerToBinary(x << shift % 32));
}
System.out.println("====================================>");
//既然有效位移次数是0-31,那么31的2进制是什么?
//是11111五个一,咱是不是只需要拿到位移次数的
//低五位就可以了?你可以打印下0-64的2进制,看看
//后5位是什么情况
//如果这个实在难以理解,你就当成是32进制,每次取
//这个数的32进制的个位数
for (int shift = 0, mask = 0x0000001f; shift <= 32; shift++)
{
System.out.println(getIntegerToBinary(x << (shift & mask)));
}
System.out.println("====================================>");
//这个眼熟不?如果 % 的方式是对的?左移-1位你怎么
//解释?当然你理解成0相当于32,-1相当于31这是可以
//但是,你怎么解释-1和31的关系?有什么证据?
//总不能说-1%32是31,那还不让人笑掉大牙?
//-1 & 0x0000001f是多少?取后五位正好是31
System.out.println(getIntegerToBinary(x << (-1 % 32)));
System.out.println(getIntegerToBinary(x << (-1 & 0x0000001f)));
//将上边的两行化简,最后就是这样的了,结果一样,那
//也就是说-1被处理,跟%没有一毛钱关系,问题发生在
//-1怎么变成31,呵呵,已经很明显了吧?
System.out.println(getIntegerToBinary(x << -1));
System.out.println(getIntegerToBinary(x << 31));
System.out.println("====================================>");
//这个足够看出来3种位移方式的区别了
//至于?的运算符,+ ^ |三种都行
//就是个孔雀开屏而已
for (int shift = 1; shift < Integer.SIZE; shift++)
{
System.out.print(getIntegerToBinary(-1 << shift));
System.out.print(" ? " + getIntegerToBinary(-1 >>> Integer.SIZE - shift));
System.out.println(" = " +getIntegerToBinary(-1 >> shift));
}
System.out.println("====================================>");
//上边的另外一种实现方式
int a = -1;
for (int i =1;i<32; i++)
{
a=a<<1;
System.out.println(getIntegerToBinary(a)+" ^ "
+getIntegerToBinary(~a)+" = "
+getIntegerToBinary(a+~a));
}
System.out.println("====================================>");
}
public static final String DEFAULT_INT_ZERO = "00000000000000000000000000000000";
public static final String getIntegerToBinary(int value)
{
String binary = Integer.toBinaryString(value);
int length = Integer.SIZE - binary.length();
return DEFAULT_INT_ZERO.substring(0, length) + binary;
}
}