为什么会在BigInteger中发生这种情况

时间:2011-08-04 05:35:49

标签: java 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);

输出为859320374而非3806908688。当我将BigInteger转换为字节数组并将此字节数组打印为整数时,为什么会发生这种情况

我也尝试使用bx.toByteArray() ,但结果相同

5 个答案:

答案 0 :(得分:1)

这是因为你正在处理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

所以这似乎是正确的。

答案 1 :(得分:1)

首先,使用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);

这样,你真的不需要明确知道数组的长度。虽然我仍然会小心地理解它是两个补码 - 谁知道你什么时候可能会意外地使用减号或类似的东西。

答案 2 :(得分:1)

如果必须手动完成,请循环执行:

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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