黑马程序员技术交流社区

标题: 大家关于来看看一个关于移位的运算 [打印本页]

作者: 吴扬    时间: 2012-6-23 02:06
标题: 大家关于来看看一个关于移位的运算
本帖最后由 吴扬 于 2012-6-24 00:51 编辑

碰到两句很简单的代码:
int i = 5;
System.out.println(i << 33);
打印结果为什么会是10呢?
5在内存中对应的二进制数应该是0000-0000 0000-0000 0000-0000 0000-0101
而它左移32位之后不应该是0吗?怎么会是10呢?
求解!

作者: 余银桂    时间: 2012-6-23 02:46
  1.       public static void  main(String args[])
  2.       {
  3.               int x = 33;
  4.               System.out.println( x%32 );  //这里是 1
  5.               int a=5;
  6.               System.out.println(a<<33); //这里是10
  7.               System.out.println(a<<1); //这里也是10
  8.               
  9.               int y = 34;
  10.               System.out.println( y%32 ); // 这里是 2
  11.               int b=5;
  12.               System.out.println(b<<34);  //这里是20
  13.               System.out.println(b<<2);  //这里也是20
  14.               
  15.       }
复制代码
刚刚查了一些资料,发现有关于这种移位运算的讲解
Java语言对位移运算作了优化处理,Java语言对a<<B转化为A<<(B%32)来处理,所以当要移位的位数B超过32时,实际上移位的位数是B%32的值,那么上面的代码中A<<33相当于A<<1,可以看着是一个循环的过程。

我顺道写了个代码测试,的确是有这种情况,楼主可以参考一下!

作者: 曾_强    时间: 2012-6-23 03:41
首先:i<<33位相当于i<<1位。

下面是Thinking in java的一段:
      如果对char,byte或者short类型的数值进行以为处理,那么在移位进行之前,他们会自动转换为int,并且得到的结果也是一个int类型的值,而右侧操作数,作为真正移位的位数,只有其二进制表示中的低5位才有用。这样可防止我们移位超过int类型值所具有的位数。(译注:因为2的5次方为32,而int类型只有32位)若对一个long类型的数值进行处理,最后得到的结果也是long。此时只会用到右操作数的低6位。以防止位移超过long类型数值具有的位数。 (page50)

针对楼主的问题:<<(左移运算符):是将左操作数向左移动右操作数指定的位数,右边移出的空位以0填充。当左操作数为int 时,移位运算符右侧的操作数只有低5位是有效的(低5位的十进制最大值为31) ,这只是为了避免全部移出失去意义。当大于32时同样适用。
当前题目中为计算 5<<33。而33的32位补码为
0000-0000 0000-0000 0000-0000 0010-0001 取其中的低5位即为00001,也就是十进制的1。即实际上只是左移1位。
所以 5<<33 相当于 5<<1。
5 的二进制为  0000-0000 0000-0000 0000-0000 0000-0101 = 5
左移一位即为 000-0000 0000-0000 0000-0000 0000-01010 = 10
作者: 吴扬    时间: 2012-6-24 00:51
谢谢大家,不过还是一知半解的,这种问题真是让人纠结!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2