Java移位运算符后面是一个负数

mac2026-09-25  10

问题引入

/* Used to shift left or right for a partial word mask */ private static final long WORD_MASK = 0xffffffffffffffffL; /** * Sets the bits from the specified {@code fromIndex} (inclusive) to the * specified {@code toIndex} (exclusive) to {@code true}. * * @param fromIndex index of the first bit to be set * @param toIndex index after the last bit to be set * @throws IndexOutOfBoundsException if {@code fromIndex} is negative, * or {@code toIndex} is negative, or {@code fromIndex} is * larger than {@code toIndex} * @since 1.4 */ public void set(int fromIndex, int toIndex) { checkRange(fromIndex, toIndex); if (fromIndex == toIndex) return; // Increase capacity if necessary int startWordIndex = wordIndex(fromIndex); int endWordIndex = wordIndex(toIndex - 1); expandTo(endWordIndex); long firstWordMask = WORD_MASK << fromIndex; long lastWordMask = WORD_MASK >>> -toIndex; if (startWordIndex == endWordIndex) { // Case 1: One word words[startWordIndex] |= (firstWordMask & lastWordMask); } else { // Case 2: Multiple words // Handle first word words[startWordIndex] |= firstWordMask; // Handle intermediate words, if any for (int i = startWordIndex+1; i < endWordIndex; i++) words[i] = WORD_MASK; // Handle last word (restores invariants) words[endWordIndex] |= lastWordMask; } checkInvariants(); }

这个函数的作用是把起、始比特位之间的比特全部置为true(二进制1b),其余位不变。其中第27行是

long lastWordMask = WORD_MASK >>> -toIndex;

以参数是30–150位为例,那么lastWord是128–192位对应的word,lastWordMask是128–150位为1b、151–192位为0b的mask。 在看这段代码之前,我理解的实现方式是

int rightShift = 64 - (toIndex % 64) long lastWordMask = WORD_MASK >>> rightShift;

rightShift表示要右移的位数。那么两种方式是如何等价的呢?

原来如此

后来去查了一下资料,移位运算符:>>(有符号右移)、<<(有符号左移)和 >>>(无符号右移)所移动的位数,为右操作数二进制表示的后5个(左操作数是int型)或后6个(左操作数是long型)比特位对应的整数。 以 WORD_MASK >>> -1为例,因为WORD_MASK为long型,所以取-1二进制表示(计算机中负数二进制为补码)的后6位(0b111111)对应的整数63,这与64 - (1 % 64)的结果相同,但由于前者是比特位运算,所以速度更快。

附上Java原始文档对移位运算符讲解的链接–Shift Operators.

最新回复(0)