0

bitwiseやBigIntを使用しているときに次のような現象が発生することを理解しようとしています。目的は2つのLong値を組み合わせて「128ビットBigInt」を得ることです。scala.math.BigIntビット演算を使用する場合の制限はありますか?

val uuid = java.util.UUID.fromString("6fcb514b-b878-4c9d-95b7-8dc3a7ce6fd8") 
val msb = BigInt(uuid.getMostSignificantBits) 
// => 8055621744141552797 
val lsb = BigInt(uuid.getLeastSignificantBits) 
// => -7658496769846775848 

(あなたがそれを無視することができるようにUUIDは、再現可能な2つのLong値を提供する以外の目的を果たすしません):

まずは、2つのLong値を作成してみましょう。

考え方は、lsbとビット単位またはを使用してマージする前に、左にmsbビットを64ビットシフトすることです。

val result = (msb << 64) | lsb 

ただし、結果はlsbになります。換言すれば、((msb << 64) | lsb) == lsbtrueである。それ以外は、((msb << 64) & lsb) == (msb << 64)trueです。

なぜですか?

編集:

ビットシフトが動作するよう、msb << 64の中間結果は、127個のバイナリ数字(おそらく先頭のゼロ)を有しています。

+0

負の値の符号ビットが繰り越されています。それらの先頭のビットはすべて、ORをとったときにシフトされた値を消去します。 2つの正の 'Long'値で動作するはずです。 – jwvh

+0

もちろん、ありがとう。何らかの理由で私は負の数の先頭の1は64ビットを超えません。 – fxlae

答えて

1

ここには、あなたが何をしているのかを知る方法があります。

import java.nio.ByteBuffer 

val uuid = java.util.UUID.fromString("6fcb514b-b878-4c9d-95b7-8dc3a7ce6fd8") 

val bb = ByteBuffer.allocate(16) 
bb.putLong(uuid.getMostSignificantBits) 
bb.putLong(uuid.getLeastSignificantBits) 

val result: BigInt = bb.array.foldLeft(BigInt(0))((bi,b) => (bi << 8)|(0xFF & b)) 
// result = 148599992668788990968304946804723445720 

// proof it works 
println(f"$result%x") // 6fcb514bb8784c9d95b78dc3a7ce6fd8 
+0

ありがとう、それは動作します。とにかく 'ByteBuffer'と' Array [Byte] 'が必要なので、' BigInt(bb.array) 'だけでも可能です。 – fxlae

関連する問題