Pramod
Pramod

Reputation: 1461

Why is this happening in BigInteger

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

The output is 859320374 instead of 3806908688. Why is this happening when I'm converting a BigInteger into a byte array and printing this byte array as an integer

I also tried using bx.toByteArray() but the result is same

Upvotes: 1

Views: 426

Answers (5)

vanje
vanje

Reputation: 10383

This is because you are working of the byte array of the string representation of the BigInteger. Use BigInteger.toByteArray() instead.

Update: If I try this:

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

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

Then the output is:

bx    : 3806908688
bxCopy: 3806908688

So this seems correct.

Upvotes: 1

MGwynne
MGwynne

Reputation: 3522

Firstly, use BigInteger.toByteArray, whatever you are doing with .toString and .getBytes won't work.

Secondly, BigInteger.toByteArray will return a byte array in twos-complement. As your number is greater than 2^31, it will take 5 bytes, not 4. See Java BigInteger.toByteArray docs . Or see the output of System.out.println(x.length);.

So you need:

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

    }
}

which yields:

5
3806908688

Note also that I'm using long not int, to ensure the value fits in the type.

You'd also be better off using a for loop:

long l = 0;

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

System.out.println(l);

That way, you don't really need to know the length of the array explicitly. Although I'd still be careful to understand that it is in twos complement - who knows when you might accidently use minus numbers or something similar.

Upvotes: 1

Arne Deutsch
Arne Deutsch

Reputation: 14769

BigInteger has a method toByteArray, use this to get at the bytes. First converting it to a string and get the bytes from there is rather ... strange.

Here's a test program that demonstrates how to convert to an byte array and back:

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

Prints:

12345678901234567890
12345678901234567890

Upvotes: 0

pmnt
pmnt

Reputation: 379

If you have to do it manually, do it in a loop:

// 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;

Alternatively you could just use methods offered by BigInteger:

int someInt = bigInt.intValue();
long someLong = bigInt.longValue();

Upvotes: 1

Bohemian
Bohemian

Reputation: 425033

Because bx.toString(10).getBytes() is 10 bytes (one for each digit of 3806908688), not 4 bytes long as your code seems to assume (your "iteration" stops at 4).

Consider using a for loop, like this, which will work no matter how many bytes are in the number:

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

Upvotes: 0

Related Questions