问题
想要了解Java内部如何处理位移长度是负数的,如100 << -5
的值是多少?问题的来源是JDK的Integer
类中有如下两个方法:
public static int rotateLeft(int i, int distance) {
return (i << distance) | (i >>> -distance);
}
public static int rotateRight(int i, int distance) {
return (i >>> distance) | (i << -distance);
}
有意思的地方在于移位长度使用了负数。它的原理是什么?
讨论
《核心Java》一书说右操作数在执行位移前需要对32取模,显然对于负数的情况不能适用,因为在Java中,负数取模之后依然是负数。《Java编程思想》中认为只有右操作数的低5位参与运算。按照补码的定义,对于任意的整数,x,0<x<32,都满足-x
的低5位等于32-x
。对于任何不在此范围内的整数都可以通过取模映射进来。
out.println(toBinaryString(-5));
out.println(toBinaryString(32-5));
out.println(toBinaryString(-32-5));
out.println(toBinaryString(32+32-5));
代码输出如下:
11111111111111111111111111111011
11011
11111111111111111111111111011011
111011
可以看到它们的低5位都是11011
。从而不难看出,i >>> -distance
等于i >>> (32-distance%32)
,i << -distance
等于i << (32-distance%32)
。
参考阅读
《The Java Language Specification, Java SE 8 Edition.》 15.17.3 Remainder Operator %
《Thinking in Java》 Shift operators
《Core Java. Volume I·Fundamentals》 Bitwise Operators