BigInteger.toByteArray()返回有目的的前导零?

5 java biginteger

我正在将bigints转换为二进制,radix16和radix64编码,并看到神秘的msb零填充.这是一个大问题,我可以通过剥离零填充或者做其他事情来解决这个问题吗?

我的测试代码:

    String s;
    System.out.printf( "%s length %d\n", s = "123456789A", (new BigInteger( s, 16 )).toByteArray().length );
    System.out.printf( "%s length %d\n", s = "F23456789A", (new BigInteger( s, 16 )).toByteArray().length );
Run Code Online (Sandbox Code Playgroud)

产生输出:

    123456789A length 5
    F23456789A length 6
Run Code Online (Sandbox Code Playgroud)

其中较长的阵列在前面没有填充.检查BigInteger.toByteArray()后,我看到:

public byte[] toByteArray() {
    int byteLen = bitLength()/8 + 1;
    byte[] byteArray = new byte[byteLen];
Run Code Online (Sandbox Code Playgroud)

现在,我可以找到private int bitLength;,但是我无法找到bitLength()的定义,以确定这个类的确切原因 - 也许连接到符号扩展?

Jon*_*eet 11

是的,这是记录在案的行为:

字节数组将采用big-endian字节顺序:最重要的字节位于第0个元素中.该数组将包含表示此BigInteger所需的最小字节数,包括至少一个符号位,即(ceil((this.bitLength() + 1)/8)).

bitLength()记录为:

返回此最小二进制补码表示中的位数BigInteger,不包括符号位.

换句话说,无论符号如何,具有相同幅度的两个值将始终具有相同的位长度.将a BigInteger视为无符号整数和符号位 - 并toByteArray()返回来自两个部分的所有数据,即"无符号整数所需的位数,以及符号的一位".


Adr*_*lie -1

感谢乔恩·斯基特的回答。这是我用来转换的一些代码,很可能可以对其进行优化。

import java.math.BigInteger;
import java.util.Arrays;

public class UnsignedBigInteger {

    public static byte[] toUnsignedByteArray(BigInteger value) {
        byte[] signedValue = value.toByteArray();
        if(signedValue[0] != 0x00) {
            throw new IllegalArgumentException("value must be a psoitive BigInteger");
        }
        return Arrays.copyOfRange(signedValue, 1, signedValue.length);
    }

    public static BigInteger fromUnsignedByteArray(byte[] value) {
        byte[] signedValue = new byte[value.length + 1];
        System.arraycopy(value,  0, signedValue, 1, value.length);
        return new BigInteger(signedValue);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 只是添加一个注释来说明代码不正确。仅当 Java BigInteger 是一个正值且其大小设置为最高位(不包括符号位)时,才会在其前面添加一个额外的零字节。原始帖子中的输入清楚地表明了这一点。“F23456789A”在第一个字节“F2”集中具有最高位,因此它需要额外的字节(以包含符号位)。`123456789A` 没有。同样,“723456789A”也没有。但“823456789A”确实如此。这很容易检查。 (4认同)