【问题标题】:Fast way to switch bits order? [closed]切换位顺序的快速方法? [关闭]
【发布时间】:2015-05-12 05:43:53
【问题描述】:

我有一个这样的二进制文件

10011011

我的数据存储像这样10,01,10,11,但我想像这样重新排序

11100110

数据看起来像11,10,01,10。此操作与ByteOrder转换相同,但在位级别。

有什么快速的方式来做到这一点?

目前,我必须将其解码为四个 int,然后合并为一个。

【问题讨论】:

  • 你到底想做什么?现在是时候真正决定你需要什么语言了 java、c 还是 go?或者你认为人们会用 3 种语言给你写信吗?
  • 这个问题只有字节或字节顺序,希望更多人能看到,所以我标记了我知道的语言。
  • 我不认为这是引起注意的正确方法(是的,它现在有效),但用cc++pythonphp标记问题, javascript, haskel, ruby, java, objective-c 只是为了引起注意不是很好。
  • 正确的解决方案是使用基于半字节的查找表。无论如何,我不会回答这个问题,因为我不知道所有 3 种语言...
  • @wener,观察到“为 [you] 工作 [ed]”的粗鲁行为并不能证明这一点!它只是表明你不在乎别人的时间/精力。

标签: java c go byte endianness


【解决方案1】:

您可以在一个步骤中使用位掩码和位移位来完成此操作,而无需将其分解为 4 个不同的变量:

Go 解决方案(在 Go Playground 上尝试):

i := 0x9b // 10011011
fmt.Printf("%b\n", i)

i = (i&0x03)<<6 | (i&0x0c)<<2 | (i&0x30)>>2 | (i&0xc0)>>6
fmt.Printf("%b\n", i)

输出:

10011011
11100110

在 Java 中:

int i = 0x9b; // 10011011
System.out.printf("%x\n", i);

i = (i & 0x03) << 6 | (i & 0x0c) << 2 | (i & 0x30) >> 2 | (i & 0xc0) >> 6;
System.out.printf("%x\n", i);

输出(是十六进制,但代表相同的数字):

9b
e6

由于每个位组(2 位组)都必须从输入中的原始位置移动,我认为您不能以更少的步骤(如屏蔽和移位步骤)来完成它。如果这对您来说还不够快,那么加快速度的唯一选择是预先计算转换并将结果存储在数组中,如@ruakh 的回答中所述。当然,如果我们允许超过 8 位,这将变得不可行。

【讨论】:

  • 我是这样编码的,但是有什么简单的方法可以不拆分合并?
【解决方案2】:

可能最快的方法是预先计算所有值的表:

final int[] values = new int[256];
for (int i = 0; i < 256; ++i) {
    values[i] = (i & 0b1100_0000) >> 6
                | (i & 0b0011_0000) >> 2
                | (i & 0b0000_1100) << 2
                | (i & 0b0000_0011) << 6;
}

然后使用数组查找而不是位操作。

当然,您会想要配置文件。

【讨论】:

  • 我将你标记为答案,因为这种方式足够快!
  • 另外,您可以基于半字节查找表,这样它就不会消耗太多内存。它应该是const 并已初始化,而不是在运行时设置。
  • @Lundin:Java 没有 const 关键字;我的示例并没有显示它是在运行时设置的,特别是,而是简单地显示了生成/填充数组的代码。至于基于半字节的查找——我不确定。正如我在回答中所说,OP 应该配置文件。位旋转实际上可能比数组查找更快。
猜你喜欢
  • 1970-01-01
  • 2012-02-18
  • 2018-09-28
  • 1970-01-01
  • 1970-01-01
  • 2021-08-01
  • 1970-01-01
  • 2016-04-03
  • 1970-01-01
相关资源
最近更新 更多