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

发布于 2024-11-28 05:11:00 字数 517 浏览 0 评论 0原文

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() 但结果是相同的

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

呆头 2024-12-05 05:11:00

如果您必须手动执行此操作,请在循环中执行:

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

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();
余生再见 2024-12-05 05:11:00

首先,使用 BigInteger.toByteArray,无论您使用 .toString 和 getBytes 做什么都不起作用。

其次,BigInteger.toByteArray 将返回一个二进制补码的字节数组。由于您的数字大于 2^31,因此需要 5 个字节,而不是 4 个字节。请参阅 Java BigInteger.toByteArray 文档 。或者查看 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);

这样,您实际上不需要显式地知道数组的长度。尽管我仍然会小心地理解它是二进制补码 - 谁知道你什么时候可能会意外地使用负数或类似的东西。

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.

兰花执着 2024-12-05 05:11:00

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

所以这似乎是正确的。

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.

寒江雪… 2024-12-05 05:11:00

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

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;
}
ˉ厌 2024-12-05 05:11:00

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文