変数がlong
あり、バイト順序を逆にする必要があります。例:B1, B2, ... , B8
で構成されるlongを返す必要がありB8, B7, ..., B1
ます。ビット演算を使用してそれを行うにはどうすればよいですか?
5 に答える
Long.reverseBytes(long)を使用できます
または、ビット演算を含むその他のメソッドについては、このスタックオーバーフローの質問を参照してください。
ここにあなたが好むかもしれない別の方法があります、私はまだ上記をお勧めしますが、あなたが簡単に間違いを犯すことができるビット単位よりも良いです。
byte[] bytes = ByteBuffer.allocate(8).putLong(someLong).array();
for (int left = 0, right = bytes.length - 1; left < right; ++left, --right) {
byte temp = bytes[left];
bytes[left] = bytes[right];
bytes[right] = temp;
}
ビット単位のソリューションは面倒で、何をしているのかわからない場合は非常に簡単に混乱するため、ビット単位のソリューションからあなたを遠ざけようとしています...しかし、ビット単位は次のようになります。
byte[] bytes = new byte[8];
// set the byte array from smallest to largest byte
for(int i = 0; i < 8; ++i) {
byte[i] = (your_long >> i*8) & 0xFF;
}
// build the new long from largest to smallest byte (reversed)
long l = ((buf[0] & 0xFFL) << 56) |
((buf[1] & 0xFFL) << 48) |
((buf[2] & 0xFFL) << 40) |
((buf[3] & 0xFFL) << 32) |
((buf[4] & 0xFFL) << 24) |
((buf[5] & 0xFFL) << 16) |
((buf[6] & 0xFFL) << 8) |
((buf[7] & 0xFFL) << 0) ;
Long.reverseBytes
ビット演算を使用する代わりに使用することをお勧めします。詳細については、Javaリファレンスを参照してください。
それ以外の場合は、JDKソース(JDKフォルダー内のsrc.zip)を確認できますがLong.java
、Oracleの著作権に注意してください。
レジスタをエンディアンスワップするために使用できる古いトリックは次のとおりです。
static long swapblock(long a, long mask, int shift) {
long b1 = a & mask; // extract block
long b2 = a ^ b1; // extract remaining bits
return (b1 << shift) |
((b2 >> shift) & mask); // mask again to clear sign extension
}
static long endianswap(long a) {
a = swapblock(a, 0x00000000ffffffffL, 32);
a = swapblock(a, 0x0000ffff0000ffffL, 16);
a = swapblock(a, 0x00ff00ff00ff00ffL, 8);
return a;
}
目的のレベルに到達するまで、サブブロックを段階的に交換するという考え方です。サイズ4、2、および1のスワップを追加することにより、これをビットミラー機能に変更できます。
Javaには符号なし型がないため、注意が必要なビットは1つだけです。右にシフトするときは、上位ビットをマスクする必要があります。これは、符号ビットがシフト量によって複製され、上位ビットが1(0x8000000000000000 >> 8
is 0xFF80000000000000
)で埋められるためです。
long reverse(long x){
x = (x >> 32) | (x << 32); // step 1
x = ((x & 0xffff0000ffff0000 ) >> 16)
| ((x & 0x0000ffff0000ffff ) << 16); // step 2
x = ((x & 0xff00ff00ff00ff00 ) >> 8)
| ((x & 0x00ff00ff00ff00ff ) << 8); // step 3
return x;
}
ビット演算子がO(1)時間で機能すると仮定すると、逆関数はO(lg(ビット数))時間で機能します。
説明
ステップ0:B1 B2 B3 B4 B5 B6 B7 B8
ステップ1:B5 B6 B7 B8 B1 B2 B3 B4
ステップ2:B7 B8 B5 B6 B3 B4 B1 B2
ステップ3:B8 B7 B6 B5 B4 B3 B2 B1
ループのあるわかりやすい答え:
public static long byteReverse(long a) {
long result = 0;
for(int i = 0; i < 8; i++){
// grab the byte in the ith place
long x = (a >> (i*8)) & (0b11111111);
result <<= 8;
result |= x;
}
return result;
}
ビット単位のみ:
public static long byteReverse(long a) {
a = (a << 32) | (a >>> 32);
a = ((a & 0xffff0000ffff0000L) >>> 16) | ((a & 0x0000ffff0000ffffL) << 16);
a = ((a & 0x00ff00ff00ff00ffL) << 8) | ((a & 0xff00ff00ff00ff00L) >>> 8);
return a;
}