Как преобразовать BigDecimal Java в обычный байтовый массив (не 2 дополнения) - PullRequest
3 голосов
/ 29 мая 2011

Как мне преобразовать большое целое число в байтовый массив, который не в формате дополнения до 2.По сути, мне нужно только преобразовать положительные числа и не нужен бит знака.

Таким образом, что-то вроде 10 станет байтом 0x0a т.е.-> 00001010

[Обновить] Согласно комментарию, я попробовал это

public void testBinary()
{
    BigDecimal test = new BigDecimal(35116031);
    BigInteger theInt = test.unscaledValue();
    byte[] arr = theInt.toByteArray();
    System.out.println(getCounterVal(arr, new BigInteger("256")));
}
public BigInteger getCounterVal(byte[] arr, BigInteger multiplier)
{
    BigInteger counter = BigInteger.ZERO;
    for(int i = (arr.length - 1); i >=0; i--)
    {
        int b = arr[i];
        //int val = (int) b & 0xFF;
        BigInteger augend = BigInteger.valueOf(b);
        counter = counter.add(augend.multiply(multiplier.pow(i)));
    }
    return counter;
}

Полученное значение выхода было -19720446 И с // int val = (int) b & 0xFF;uncommented и использованный как augend, я получил значение 4292024066

[Update2] Вот тест, который я выполнил, который работает.Не уверен, что это без ошибок, но выглядит хорошо.

@Test
public void bigIntegerToArray()
{
    BigInteger bigInt = new BigInteger("35116444");
    byte[] array = bigInt.toByteArray();
    if (array[0] == 0)
    {
        byte[] tmp = new byte[array.length - 1];
        System.arraycopy(array, 1, tmp, 0, tmp.length);
        array = tmp;
    }

    BigInteger derived = BigInteger.ZERO;
    BigInteger twofiftysix = new BigInteger("256");
    int j = 0;
    for (int i = array.length - 1; i >= 0; i--)
    {
        int val = (int) array[i] & 0xFF;
        BigInteger addend = BigInteger.valueOf(val);
        BigInteger multiplier = twofiftysix.pow(j);
        addend = addend.multiply(multiplier);
        derived = derived.add(addend);
        j++;
    }

    Assert.assertEquals(bigInt, derived);
}

Ответы [ 4 ]

9 голосов
/ 29 мая 2011

Разница в значительной степени концептуальная. Номера без знака одинаковы в 2-х комплиментах. Комплимент 2 просто описывает, как представлять отрицательные числа, которых, как вы говорите, у вас нет.

т.е. 10 - это 00001010 в подписанном и неподписанном представлении.

Чтобы получить байты из BigDecimal или BigInteger, вы можете использовать методы, которые он предоставляет.

BigDecimal test = new BigDecimal(35116031);
BigInteger theInt = test.unscaledValue();
byte[] arr = theInt.toByteArray();
System.out.println(Arrays.toString(arr));

BigInteger bi2 = new BigInteger(arr);
BigDecimal bd2 = new BigDecimal(bi2, 0);
System.out.println(bd2);

печать

[2, 23, -45, -1]
35116031

Байты правильные и воспроизводят одно и то же значение.

В способе восстановления вашего BigInteger есть ошибка. Вы предполагаете, что байтовая сериализация имеет младший порядок байтов, когда Java обычно использует big endian http://en.wikipedia.org/wiki/Endianness

1 голос
/ 29 мая 2011

Попробуйте разделить число в байтах, разделив его на 256 в каждой итерации и используя остаток, и поместите все эти байты в массив.

0 голосов
/ 29 мая 2011

знаковый бит в 2-комплимент для положительных чисел равен 0

, поэтому для положительных чисел знак без знака

не имеет значения
0 голосов
/ 29 мая 2011

Если значение меньше размера long, тогда используйте longValue, а затем преобразуйте long в байты. Если значение больше, чем long, то, вероятно, вам нужно использовать итеративный подход, многократно делить число на 256, принимая остаток в качестве следующего байта, а затем повторять, пока не получите ноль. Байты будут генерироваться справа налево. Числа со знаком требуют обдумывания (для получения результатов с дополнением 2s), но не намного сложнее.

...