大家都知道java有关整数的移位运算符有三个<< ,>>, >>>。但是我看了几本书对他们都是一带而过有一个问题一直困扰着我。
书上都说〈〈右移动n位这个运算是起到2的n次方的作用,但是显然如果移出去的位里有1的话结果就不会增大2的n次方的作用了,其结果就是不可预测的,但是我看了java核心技术和java编程思想都没有涉及这个问题,都是一带说是增大2的n次方的作用。显然这个两个〉〉 , >>>也有移出的位有1的话错误的问题。
希望指点,谢谢!
书上都说〈〈右移动n位这个运算是起到2的n次方的作用,但是显然如果移出去的位里有1的话结果就不会增大2的n次方的作用了,其结果就是不可预测的,但是我看了java核心技术和java编程思想都没有涉及这个问题,都是一带说是增大2的n次方的作用。显然这个两个〉〉 , >>>也有移出的位有1的话错误的问题。
希望指点,谢谢!
你说的话我明白事实上如果作为int形的变量,左移n位的话,java自动对n取模32(因为int一共有32位,如果是long形就取模64)如果调试int i;i<<34和i<<2结果i都会是4。但是显然作为int的01011110000000000000000000000000左移两位结果就不对了,而且它也没出他的表示范围,楼上有的兄弟回答的太草率
System.out.println(Integer.toHexString(0xFFFFFFFF >> 8));//>>有符合右移(符号高位决定),,所以结果是0xFFFFFFFF ,即 -1
System.out.println(Integer.toHexString(0x000000FF<< 8));//左移,,所以结果是0xFFFFFF00
<< 往左移 是1补1,是0补0。 左移n位就是乘以2的n次方。
>> 往右移 是1补1,是0补0。 右移n位就是除以2的n次方。
>>> 无符号右移 始终补0。
首先纠正楼主错误,‘<<’为左移符号。是这样的,左移在补码中只是在末尾加0,起到扩大2的n次方的作用。
比如101这个二进制数,也就是5(十进制),左移一位后变为1010,十进制是10,起到了x2的作用。这里所说的“如果移出去的位里有1的话结果就不会增大2的n次方的作用了,其结果就是不可预测的”是指:如果对数的长度有要求,比如只能用3位二进制表示整数,还用上面的例子101,移动一位后是010,第一个1已经移出去,结果是2(十进制),没有扩大2倍,所以他说其结果就是不可预测的。而楼主下面的话:
"显然这个两个〉〉 , >>>也有移出的位有1的话错误的问题。" 是错误的。因为右移和左移的规律是不同的,移位后的第一位是“按符号移动”,就不会出现以上问题。所以,楼主的书上所言是完全正确的。还要说明一点,一定要清楚数字在机器内部是按补码存储的,比如 int a=5,在内部,已经存储为00000000000000000000000000000101(32位),而不用你做任何转换。
首先说<<左移。别说左移出二进制1会出问题,就是左移出0的话超出变量的表示范围也一样会出问题
也就是说,左移的前提是不要超出数的表示范围的话,2的n次方这个结论还是正确的。例子是int x=0x8fffffff;x<<1(超出数的表示范围)。之所以会犯我以前认识上的错误,是因为写成十进制后忽略了前面有那么多零比如说int i=5;事实上因为int有32位存储,要左移29次的话才会超出范围。但是>>就不一样了很容易就能把二进制1移出去这样得到的结果其实是整除2的n次方的结果