开发者

Why is this happening in BigInteger

开发者 https://www.devze.com 2023-03-24 22:59 出处:网络
BigInteger bx=new BigInteger(\"3806908688\"); byte x[]=new byte[4]; String s=bx.toString(10); System.out.println(\"string: \"+s);
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


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


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.


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.


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


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
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号