大家都知道java有关整数的移位运算符有三个<< ,>>, >>>。但是我看了几本书对他们都是一带而过有一个问题一直困扰着我。
    书上都说〈〈右移动n位这个运算是起到2的n次方的作用,但是显然如果移出去的位里有1的话结果就不会增大2的n次方的作用了,其结果就是不可预测的,但是我看了java核心技术和java编程思想都没有涉及这个问题,都是一带说是增大2的n次方的作用。显然这个两个〉〉 , >>>也有移出的位有1的话错误的问题。
希望指点,谢谢!

解决方案 »

  1.   

    楼主说得没错,但是<<使用时有个前提,就是运算的结果必须在进行运算的对象的取值范围内,所以楼主所说的   “显然如果移出去的位里有1的话结果就不会增大2的n次方的作用了,其结果就是不可预测的”  是不准确的。
      

  2.   

    congliu()你好
       你说的话我明白事实上如果作为int形的变量,左移n位的话,java自动对n取模32(因为int一共有32位,如果是long形就取模64)如果调试int i;i<<34和i<<2结果i都会是4。但是显然作为int的01011110000000000000000000000000左移两位结果就不对了,而且它也没出他的表示范围,楼上有的兄弟回答的太草率
      

  3.   

    System.out.println(Integer.toHexString(0xFFFFFFFF >>> 8));//>>>无符合右移,填0,所以结果是0x00FFFFFF
    System.out.println(Integer.toHexString(0xFFFFFFFF >> 8));//>>有符合右移(符号高位决定),,所以结果是0xFFFFFFFF ,即 -1
    System.out.println(Integer.toHexString(0x000000FF<< 8));//左移,,所以结果是0xFFFFFF00
      

  4.   

    有很重要的一点楼主没有搞清楚,就是机器数的存放是用补码.1、正数移动。正数由于首位是零,所以在没有溢出的情况,左移末位补0,右移首位补0。如果左移后首位,变1,这个数就变成负数了了,说明正溢出了。右移动如果全变0,说明这个数已经小于机器数可表示范围(int型小于1大于0了)2、负数移动。规则基本类似,左移的时候末位补0,如果首位变0,说明此数负溢出,右移的时候首位保持1,如果除了首位其他都是0,说明此数已经超出表示范围(int型小于0大与-1)应该够详细了吧
      

  5.   

    关于移位操作 
    << 往左移 是1补1,是0补0。 左移n位就是乘以2的n次方。
    >> 往右移 是1补1,是0补0。 右移n位就是除以2的n次方。
    >>> 无符号右移 始终补0。
      

  6.   

    "书上都说〈〈右移动n位这个运算是起到2的n次方的作用,但是显然如果移出去的位里有1的话结果就不会增大2的n次方的作用了,其结果就是不可预测的,.."
    首先纠正楼主错误,‘<<’为左移符号。是这样的,左移在补码中只是在末尾加0,起到扩大2的n次方的作用。
    比如101这个二进制数,也就是5(十进制),左移一位后变为1010,十进制是10,起到了x2的作用。这里所说的“如果移出去的位里有1的话结果就不会增大2的n次方的作用了,其结果就是不可预测的”是指:如果对数的长度有要求,比如只能用3位二进制表示整数,还用上面的例子101,移动一位后是010,第一个1已经移出去,结果是2(十进制),没有扩大2倍,所以他说其结果就是不可预测的。而楼主下面的话:
    "显然这个两个〉〉 , >>>也有移出的位有1的话错误的问题。" 是错误的。因为右移和左移的规律是不同的,移位后的第一位是“按符号移动”,就不会出现以上问题。所以,楼主的书上所言是完全正确的。还要说明一点,一定要清楚数字在机器内部是按补码存储的,比如 int a=5,在内部,已经存储为00000000000000000000000000000101(32位),而不用你做任何转换。
      

  7.   

    java里面的移位,就是用补码来移位的!也就是补码移位.
      

  8.   

    借问c语言中->是做什么用的?
      

  9.   

    感谢个位的回复,昨天在机器上狂试验了一下,感觉应该是这么回事情。
    首先说<<左移。别说左移出二进制1会出问题,就是左移出0的话超出变量的表示范围也一样会出问题
    也就是说,左移的前提是不要超出数的表示范围的话,2的n次方这个结论还是正确的。例子是int x=0x8fffffff;x<<1(超出数的表示范围)。之所以会犯我以前认识上的错误,是因为写成十进制后忽略了前面有那么多零比如说int i=5;事实上因为int有32位存储,要左移29次的话才会超出范围。但是>>就不一样了很容易就能把二进制1移出去这样得到的结果其实是整除2的n次方的结果