1

给定一个long字节WXYZ(每个字母都是一个字节),我想要一些快速的位旋转代码,它将创建两个longs与原始字节相同的字节,但与 0 字节交错。

例如,给定longwith 值ABCDEFGH(每个字母为一个字节),产生两个 long:

0A0B0C0D
0E0F0G0H

相当于,但比:

long result1 = expand((int)(input >>> 32));
long result2 = expand((int)input);

long expand(int inputInt) {
  long input = intputInt;
  return
    (input & 0x000000FF)       | 
    (input & 0x0000FF00) <<  8 | 
    (input & 0x00FF0000) << 16 | 
    (input & 0xFF000000) << 24;
}
4

3 回答 3

3

以下对我来说大约快 25%(Java 7,使用 Google Caliper 进行基准测试),YMMV 当然可能会根据您的编译器而有所不同:

long a = (input | (input << 16));
long result = (a & 0xFF000000FFL) + ((a & 0xFF000000FF00L) <<8);

这个想法是使用一些额外的并行性与原始方法相比。

第一行是一个巧妙的技巧,它会在 17-32 位产生垃圾,但你不在乎,因为无论如何你都会把它屏蔽掉。:-)

于 2012-12-11T06:36:37.887 回答
0
long expand(int inputInt) {
  long input = intputInt;
  return
    (input & 0x000000FF) <<  8 | 
    (input & 0x0000FF00) << 16 | 
    (input & 0x00FF0000) << 24 | 
    (input & 0xFF000000) << 32;
}
于 2012-12-11T05:51:26.057 回答
0

在 C++ 中,您可以尝试使用联合:

typedef union
{
    char bytes[8];
    long value;
} PlatformSpecificSolution;

long expand(int valueInt)
{
    PlatformSpecificSolution pss;
    pss.value = valueInt;
    pss.bytes[6] = pss.bytes[3]; pss.bytes[3] = 0;
    pss.bytes[4] = pss.bytes[2]; pss.bytes[2] = 0;
    pss.bytes[2] = pss.bytes[1]; pss.bytes[1] = 0;
    // pss.bytes[0] = pss.bytes[0];
    return pss.value;
 }

我不知道这是否更快(您必须在要支持的平台上运行基准测试)。这个解决方案肯定更容易出错。您应该始终问自己,性能优势是否超过了可维护性较差的代码的劣势。

于 2012-12-11T06:22:19.280 回答