我相信您可以使用 java.math.BigInteger 来完成此操作,它支持任意大数的移位。这样做的优点是简单,但缺点是不能填充到原始字节数组大小,即输入可能是 16 个字节,但输出可能只有 10 个字节等,需要额外的逻辑。
大整数方法
byte [] array = new byte[]{0x7F,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
// create from array
BigInteger bigInt = new BigInteger(array);
// shift
BigInteger shiftInt = bigInt.shiftRight(4);
// back to array
byte [] shifted = shiftInt.toByteArray();
// print it as hex
for (byte b : shifted) {
System.out.print(String.format("%x", b));
}
Output
7f1122334455667 <== shifted 4 to the right. Looks OK
长操纵
我不知道为什么你想这样做作为rotateRight(),因为这让生活变得更加困难,你必须在K1等左侧出现的位上留空。你最好使用shift IMO 如下所述。我使用了 20 的移位(可以被 4 整除),这样更容易看到半字节在输出中的移动。
1)使用ByteBuffer从16字节数组形成两个long
byte[] array = { 0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77 };
ByteBuffer buffer = ByteBuffer.wrap(array);
long k1 = buffer.getLong();
long k2 = buffer.getLong();
2)将每个长n位右移
int n = 20;
long k1Shift = k1 >> n;
long k2Shift = k2 >> n;
System.out.println(String.format("%016x => %016x", k1, k1Shift));
System.out.println(String.format("%016x => %016x", k2, k2Shift));
0000111122223333 => 0000000001111222
4444555566667777 => 0000044445555666
确定 k1 中“被推离边缘”的位
long k1CarryBits = (k1 << (64 - n));
System.out.println(String.format("%016x => %016x", k1, k1CarryBits));
0000111122223333 => 2333300000000000
将 K1 进位位连接到右侧的 K2 上
long k2WithCarray = k2Shift | k1CarryBits;
System.out.println(String.format("%016x => %016x", k2Shift, k2WithCarray));
0000044445555666 => 2333344445555666
将两个 long 写回 ByteBuffer 并提取为字节数组
buffer.position(0);
buffer.putLong(k1Shift);
buffer.putLong(k2WithCarray);
for (byte each : buffer.array()) {
System.out.print(Long.toHexString(each));
}
000011112222333344445555666