简体   繁体   English

在字节数组上执行右位旋转/循环移位的最快方法是什么

[英]What's the fastest way to do a right bit rotation/circular shift on a byte array

If I have the array: 如果我有阵列:

{01101111,11110000,00001111} // {111, 240, 15}

The result for a 1 bit shift is: 1位移位的结果是:

{10110111,11111000,00000111} // {183, 248, 7}

The array size is not fixed, and the shifting will be from 1 to 7 inclusive. 阵列大小不固定,移位将从1到7(包括1和7)。 Currently I have the following code (which works fine): 目前我有以下代码(工作正常):

private static void shiftBitsRight(byte[] bytes, final int rightShifts) {
   assert rightShifts >= 1 && rightShifts <= 7;

   final int leftShifts = 8 - rightShifts;

   byte previousByte = bytes[0]; // keep the byte before modification
   bytes[0] = (byte) (((bytes[0] & 0xff) >> rightShifts) | ((bytes[bytes.length - 1] & 0xff) << leftShifts));
   for (int i = 1; i < bytes.length; i++) {
      byte tmp = bytes[i];
      bytes[i] = (byte) (((bytes[i] & 0xff) >> rightShifts) | ((previousByte & 0xff) << leftShifts));
      previousByte = tmp;
   }
}

Is there a faster way to achieve this than my current approach? 有没有比我目前的方法更快的方法来实现这一目标?

The only way to find out is with thorough benchmarking, and the fastest implementations will vary from platform to platfrm. 找到答案的唯一方法是彻底的基准测试,最快的实现方式因平台而异。 Use a tool like Caliper if you really need to optimize this. 如果您真的需要优化,请使用像Caliper这样的工具。

One of the things you can do is replace (byte[a]&0xff)>>b with byte[a]>>>b 您可以做的一件事是用byte[a]>>>b替换(byte[a]&0xff)>>b byte[a]>>>b

Also, you don't need &0xff when you are left shifting. 此外,当您离开时,您不需要&0xff

Although it may not matter, either adding final to tmp or moving the declaration out of the loop may help a tiny bit. 虽然可能无关紧要,但是将最终添加到tmp或将声明移出循环可能会有所帮助。

Another thing might try is: 另一件事可能是尝试:

int tmp=bytes[bytes.length-1];
for (int i = bytes.length-2; i >=0; i--) {
  tmp=(tmp<<8)|bytes[i];
  bytes[i] = (byte) (tmp>>>rightShifts);
 }

Then you solve bytes[bytes.length-1] afterwards. 然后你解决字节[bytes.length-1]。

That reverse for loop may also help if you are superstitious. 如果你迷信,反向循环也可能有所帮助。 I've seen it work before. 我以前见过它。

Loop Analysis per pass: 每次循环分析:

yours: 3 assignments, two shifts, one or, one cast. 你的:3个作业,两个班次,一个或一个演员。

mine: 2 assignments, two shifts, one or, one cast. 我的:2个任务,两个轮班,一个或一个演员。

Use ByteBuffer.wrap to get a buffer that wraps your byte[] and then use ByteBuffer.asLongBuffer() to get a view that allows you to extract and manipulate long s as suggested by @NiklasB. 使用ByteBuffer.wrap获取一个包装你的byte[]的缓冲区,然后使用ByteBuffer.asLongBuffer()获取一个视图,允许你按照@NiklasB的建议提取和操作long thus taking advantage of the hardware's ability to shift larger chunks of bits. 从而利用硬件移动较大块位的能力。

You can generalize this to longs and more than one bit shift if you like 如果您愿意,可以将其概括为longs和多位移位

// for a 1-bit rightshift:
// first rotate each byte right by one
for (i = 0; i < n; i++) b[i] = rotr(b[i], 1);
// get rightmost bit
bit = b[n-1] & 0x80;
// copy high order bit from adjacent byte
for (i = n; --i >= 1;){
    b[i] &= 0x7f;
    b[i] |= (b[i-1] & 0x80);
}
// put in the rightmost bit on the left
b[0] = (b[0] & 0x7f) | bit;

assuming rotr is defined. 假设定义了rotr

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM