Почему это происходит в BigInteger - PullRequest
1 голос
/ 04 августа 2011
BigInteger bx=new BigInteger("3806908688");

byte x[]=new byte[4];

String s=bx.toString(10);

System.out.println("string: "+s);

x=s.getBytes();

int l=0,i=0;

l |= x[i] & 0xFF;

l <<= 8;

l |= x[i+1] & 0xFF;

l <<= 8;

l |= x[i+2] & 0xFF;

l <<= 8;

l |= x[i+3] & 0xFF;

System.out.println(l);

Выход 859320374 вместо 3806908688. Почему это происходит, когда я конвертирую BigInteger в байтовый массив и печатаю этот байтовый массив как целое число

Я также пытался использовать bx.toByteArray() , но результат тот же

Ответы [ 5 ]

1 голос
/ 04 августа 2011

Если вам нужно сделать это вручную, сделайте это в цикле:

// Take care of negative values
long l = (bigInt.compareTo(BigInteger.ZERO) < 0) ? -1 : 0;
byte[] array = bigInt.toByteArray();
for(int i=0; i<array.length-1; i++) {
    l |= array[i] & 0xFF;
    l <<= 8;
}
l |= array[array.length-1] & 0xFF;

В качестве альтернативы вы можете просто использовать методы, предлагаемые BigInteger:

int someInt = bigInt.intValue();
long someLong = bigInt.longValue();
1 голос
/ 04 августа 2011

Во-первых, используйте BigInteger.toByteArray, что бы вы ни делали с .toString и .getBytes не будет работать.

Во-вторых, BigInteger.toByteArray вернет байтовый массив в два дополнения. Поскольку ваше число больше 2 ^ 31, оно займет 5 байтов, а не 4. См. Java BigInteger.toByteArray docs . Или посмотрите вывод System.out.println(x.length);.

Итак, вам нужно:

import java.math.BigInteger;

class BigIntegerTest {
    public static void main(final String[] argv) {
        BigInteger bx=new BigInteger("3806908688");

        byte x[]=new byte[5];

        x=bx.toByteArray();

        System.out.println(x.length);

        long l=0;
        int i=0;

        l |= x[i] & 0xFF;

        l <<= 8;

        l |= x[i+1] & 0xFF;

        l <<= 8;

        l |= x[i+2] & 0xFF;

        l <<= 8;

        l |= x[i+3] & 0xFF;

        l <<= 8;

        l |= x[i+4] & 0xFF;

        System.out.println(l);

    }
}

что дает:

5
3806908688

Обратите внимание, что я использую long, а не int, чтобы убедиться, что значение соответствует типу.

Вам также лучше использовать цикл for:

long l = 0;

for (int i = 0; i < x.length; ++i) {
    l <<= 8;
    l |= x[i] & 0xFF;
}

System.out.println(l);

Таким образом, вам не нужно точно знать длину массива. Хотя я все еще буду осторожен, чтобы понять, что это в дополнение к двум - кто знает, когда вы можете случайно использовать минус числа или что-то подобное.

1 голос
/ 04 августа 2011

Это потому, что вы работаете с байтовым массивом строкового представления BigInteger. Вместо этого используйте BigInteger.toByteArray ().

Обновление: Если я попробую это:

BigInteger bx = new BigInteger("3806908688");
byte[] bytes = bx.toByteArray(); 
BigInteger bxCopy = new BigInteger(bytes);

System.out.println("bx    : " + bx);
System.out.println("bxCopy: " + bxCopy);

Тогда вывод:

bx    : 3806908688
bxCopy: 3806908688

Так что это кажется правильным.

0 голосов
/ 04 августа 2011

BigInteger имеет метод toByteArray, используйте его, чтобы получить байты.Сначала преобразовать его в строку и получить оттуда байты довольно ... странно.

Вот тестовая программа, которая демонстрирует, как преобразовать в байтовый массив и обратно:

import java.math.BigInteger;

public class TestBigInteger {
    public static void main(String[] args) {
        BigInteger first = new BigInteger("12345678901234567890");
        System.out.println(first);
        BigInteger second = new BigInteger(first.toByteArray());
        System.out.println(second);
    }
}

Отпечатки:

12345678901234567890
12345678901234567890
0 голосов
/ 04 августа 2011

Поскольку bx.toString(10).getBytes() - это 10 байтов (по одному на каждую цифру 3806908688), а не 4 байта, как, по-видимому, предполагается в вашем коде (ваша "итерация" останавливается на 4).

Рассмотрите возможность использования цикла for, подобного этому, который будет работать независимо от количества байтов в числе:

long l = 0; // long is large enough to hold your number 3806908688
for (byte b : x) {
    i |= b & 0xFF;
    l <<= 8;
}
...