如何获得任意长度的BigInteger的2的补码值

时间:2016-08-12 12:38:55

标签: java android biginteger twos-complement negative-number

BigInteger中是否有方法可以获得2的补码值? 例如:如果有一个负值的BigInteger

BigInteger a = new BigInteger("-173B8EC504479C3E95DEB0460411962F9EF2ECE0D3AACD749BE39E1006FC87B8", 16);

然后我想以BigInteger形式获得2的补码

BigInteger b = E8C4713AFBB863C16A214FB9FBEE69D0610D131F2C55328B641D61EFF9037848

我可以从0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF中减去第一个BigInteger来获取第二个BigInteger但是有一个通用方法可以为任意长度的BigInteger计算这个吗?

1 个答案:

答案 0 :(得分:2)

使这个值成为它的两个补码,你将不得不操纵内容。这当然是不可能的,所以你先把内容拿出来,操纵它们然后把它们变成新的BigInteger

public static BigInteger twosComplement(BigInteger original)
{
    // for negative BigInteger, top byte is negative  
    byte[] contents = original.toByteArray();

    // prepend byte of opposite sign
    byte[] result = new byte[contents.length + 1];
    System.arraycopy(contents, 0, result, 1, contents.length);
    result[0] = (contents[0] < 0) ? 0 : (byte)-1;

    // this will be two's complement
    return new BigInteger(result);
}

public static void main(String[] args)
{
    BigInteger a = new BigInteger("-173B8EC504479C3E95DEB0460411962F9EF2ECE0D3AACD749BE39E1006FC87B8", 16);
    BigInteger b = twosComplement(a);

    System.out.println(a.toString(16).toUpperCase());
    System.out.println(b.toString(16).toUpperCase());

    // for comparison, from question:
    System.out.println("E8C4713AFBB863C16A214FB9FBEE69D0610D131F2C55328B641D61EFF9037848");
}

输出:

-173B8EC504479C3E95DEB0460411962F9EF2ECE0D3AACD749BE39E1006FC87B8
E8C4713AFBB863C16A214FB9FBEE69D0610D131F2C55328B641C61EFF9037848
E8C4713AFBB863C16A214FB9FBEE69D0610D131F2C55328B641D61EFF9037848

这个新的BigInteger实际上是两个补码,而不仅仅是对比特的重新解释。