Reputation: 1461
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
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
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
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
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
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