java - 如何 (i << 48) | ((i & 0xffff0000L) << 16) | ((i >>> 16) & 0xffff0000L) | (i >>> 48) 工作?

标签 java long-integer bit

这里是反向在 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;
}

我能看懂第 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)

但是,不知道是哪里错了,是不是错了!想了差不多一整天!

有人可以帮助我!!谢谢。

哦,我犯了这样的错误:

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)

但我也认为这是错误的!我认为正确的顺序是 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)

最佳答案

第 1 行成对交换相邻的单个位(0 <-> 1;2 <-> 3;等等)。第 2-4 行交换相邻的 2 位、4 位和 8 位序列。那时,原始值已被转换为四个 16 位的 block ,每个 block 与开始时的值相反。第 5 行然后重新排列 4 个 block 。基本上,第 5 行将两个步骤合二为一:交换两对 16 位 block 和交换一对 32 位 block 。逻辑是:

  • (i << 48)将最右边的 16 位 block 移动到左边的位置,将所有其他位保留为零
  • ((i & 0xffff0000L) << 16)将右边的第二个 block 移动到左边的第二个 block (所有其他位为零)
  • ((i >>> 16) & 0xffff0000L)将左边的第二个 block 移动到右边的第二个 block (所有其他位为零)
  • (i >>> 48)将最左边的 block 移动到正确的位置(所有其他位为零)

那么这四个值就是| -一起产生最终的逆转。如果它分两步完成,那么这两个语句看起来就像前四个语句,但具有不同的掩码模式。

我认为在第 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)

关于java - 如何 (i << 48) | ((i & 0xffff0000L) << 16) | ((i >>> 16) & 0xffff0000L) | (i >>> 48) 工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9529275/

相关文章:

c - 如何逐位打印 C double 以查看低级表示?

arrays - 高效的钻头容器

Java如何刷新jlist中的sql结果

c - printf 转换 long long 的问题

在 C 中使用 strtoull() 转换为 long long int

c - gcc long long int 宽度与 int 相同

java - 迁移到新 Roo 版本的问题

java - 上传文件的FTP服务器

java - 管理 1 个项目中的多个 Google Web Toolkit 页面

C++:可缩放数字类 - bitset<1>* 或 unsigned char*