liu*_*ori 6 java bits long-integer
这是Long中反向的实现:
public static long reverse(long i) {
// HD, Figure 7-1
i = (i & 0x5555555555555555L) << 1 | (i >>> 1) & 0x5555555555555555L;//1
i = (i & 0x3333333333333333L) << 2 | (i >>> 2) & 0x3333333333333333L;//2
i = (i & 0x0f0f0f0f0f0f0f0fL) << 4 | (i >>> 4) & 0x0f0f0f0f0f0f0f0fL;//3
i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL;//4
i = (i << 48) | ((i & 0xffff0000L) << 16) |
((i >>> 16) & 0xffff0000L) | (i >>> 48);//5
return i;
}
Run Code Online (Sandbox Code Playgroud)
我能理解第1,2,3,4行,但不能理解5!它是如何工作的?
我将64位分组为8组,即1是前8位,2是后8位,依此类推.
然后在第4行之后,序列就像 4,3,2,1,8,7,6,5
我认为第5行在|
操作之前如下工作:
6,5,0,0,0,0,0,0-->(i << 48)
8,7,0,0,0,0,0,0-->((i & 0xffff0000L) << 16)
0,0,0,0,4,3,2,1-->((i >>> 16) & 0xffff0000L)
0,0,0,0,0,0,2,1-->(i >>> 48)
Run Code Online (Sandbox Code Playgroud)
但是,我不知道它错在哪里,或者它是错的!几乎整整一天都在考虑它!
有人可以帮帮我!! 谢谢.
哦,我犯了这样的错误:
6,5,0,0,0,0,0,0-->(i << 48)
0,0,8,7,0,0,0,0-->((i & 0xffff0000L) << 16)
0,0,0,0,2,1,0,0-->((i >>> 16) & 0xffff0000L)
0,0,0,0,0,0,4,3-->(i >>> 48)
Run Code Online (Sandbox Code Playgroud)
但我认为这是错误的!我认为正确的顺序是8,7,6,5,4,3,2,1
我很抱歉我犯了一些错误!它的工作原理如下:
在第4行之后,正确的模式是:2,1,4,3,6,5,8,7
8,7,0,0,0,0,0,0-->(i << 48)
0,0,6,5,0,0,0,0-->((i & 0xffff0000L) << 16)
0,0,0,0,4,3,0,0-->((i >>> 16) & 0xffff0000L)
0,0,0,0,0,0,2,1-->(i >>> 48)
Run Code Online (Sandbox Code Playgroud)
第1行成对地交换相邻的单个位(0 < - > 1; 2 < - > 3;等等).第2-4行交换相邻的两位,4位和8位序列.此时,原始值已转换为4个16位的块,每个块与开始时的块相反.第5行然后重新排列4个块.基本上,第5行将两个步骤合二为一:交换两对16位块并交换一对32位块.逻辑是:
(i << 48)
将最右边的16位块移动到左侧位置,将所有其他位置为零((i & 0xffff0000L) << 16)
将第二个块从右边移动到左边的第二个块(所有其他位为零)((i >>> 16) & 0xffff0000L)
将第二个块从左侧移动到右侧的第二个块(所有其他位为零)(i >>> 48)
将最左边的块移动到正确的位置(所有其他位为零)然后将这四个值|
组合在一起以产生最终的反转.如果它分两步完成,那么它将是两个语句,看起来就像前四个语句,但具有不同的掩码模式.
我认为在第4行之后,模式2,1,4,3,6,5,8,7
不是4,3,2,1,8,7,6,5
你想象的那样.然后,第5行的四个部分是:
8,7,0,0,0,0,0,0-->(i << 48)
0,0,6,5,0,0,0,0-->((i & 0xffff0000L) << 16)
0,0,0,0,4,3,0,0-->((i >>> 16) & 0xffff0000L)
0,0,0,0,0,0,2,1-->(i >>> 48)
Run Code Online (Sandbox Code Playgroud)