BigInteger в байтах [] - PullRequest
       33

BigInteger в байтах []

15 голосов
/ 10 декабря 2010

Мне нужно преобразовать экземпляр Java BigInteger в его значение в байтах. Из API я получаю этот метод toByteArray(), который возвращает байт [], содержащий представление двоичного дополнения этого BigInteger.

Поскольку все мои числа являются положительными 128-битными (16 байтами) целыми числами, мне не нужна форма с 2-мя дополнениями, которая дает мне 128 бит + знак (129 бит) ...

Есть ли способ получить стандартное (без формы 2-го дополнения) представление непосредственно из BigInteger?

Если нет, то как я могу сдвинуть вправо весь массив байтов [17], чтобы потерять знаковый бит, чтобы получить массив байтов [16]?

Ответы [ 3 ]

27 голосов
/ 10 декабря 2010

Вам совсем не нужно сдвигаться. Знаковый бит является самым значимым (= крайним левым) битом вашего байтового массива. Поскольку вы знаете, что ваши числа всегда будут положительными, оно гарантированно будет равно 0. Однако массив в целом выровнен по правому краю.

Итак, есть два случая: ваш самый левый байт равен 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, то вы не можете его удалить - но ваш массив уже будет в нужном вам представлении, поэтому вам не нужно ничего делать.

Приведенный выше код должен работать в обоих случаях.

4 голосов
/ 10 декабря 2010

Первый (самый значимый) байт в байтовом массиве может содержать не только бит знака, но и обычные биты.

например. этот 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??????
3 голосов
/ 10 декабря 2010

Вы можете скопировать первый байт.Или вы можете просто проигнорировать это.

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));
...