web-dev-qa-db-ja.com

BigIntegerからbyte []

Java BigInteger インスタンスをバイト単位の値に変換する必要があります。APIから、バイトを返すこのメソッドtoByteArray()を取得します。 []このBigIntegerの2の補数表現を含みます。

私の数字はすべて正の128ビット(16バイト)整数なので、128ビット+符号ビット(129ビット)を与える2の補数形式は必要ありません。

標準(2の補数形式なし)表現をBigIntegerから直接取得する方法はありますか?

そうでない場合、byte [16]配列を取得するために、byte [17]配列全体を右シフトして符号ビットを失うにはどうすればよいですか?

15
Kami

シフトする必要はまったくありません。符号ビットは、バイト配列の最上位(=左端)のビットです。数値は常に正であることがわかっているため、0であることが保証されます。ただし、配列全体は右揃えになっています。

したがって、2つのケースがあります。左端のバイトが0x00であるかどうかです。 0x00の場合は、安全にドロップできます。

byte[] array = bigInteger.toByteArray();
if (array[0] == 0) {
    byte[] tmp = new byte[array.length - 1];
    System.arraycopy(array, 1, tmp, 0, tmp.length);
    array = tmp;
}

0でない場合、ドロップすることはできませんが、配列は既に必要な表現になっているため、何もする必要はありません。

上記のコードは両方の場合に機能するはずです。

27
Thomas

バイト配列の最初の(最上位)バイトには、符号ビットだけでなく、通常のビットも含まれる場合があります。

例えば。このBigInteger:

new BigInteger("512")
    .add(new BigInteger("16"))
    .add(new BigInteger("1"));

このビットパターンがあります:00000010 00010001

つまり、(符号ビットを含む)最上位バイトにも「通常の」ビットがあります。

それで、あなたは何を取り戻したいですか?

00000010 00010001 (what you have) or
00000100 0010001? or
10000100 01??????
4
daveb

最初のバイトをコピーすることができます。または、無視することもできます。

BigInteger bi = BigInteger.ONE.shiftLeft(127);
byte[] bytes1 = bi.toByteArray();
System.out.println(Arrays.toString(bytes1));
byte[] bytes = new byte[bytes1.length-1];
System.arraycopy(bytes1, 1, bytes, 0, bytes.length);
System.out.println(Arrays.toString(bytes));
3
Peter Lawrey