如何获取任意长度的 BigInteger 的 2 的补码值
How to get the 2's complement value of a BigInteger of arbitrary length
BigInteger中有获取2的补码的方法吗?
例如:如果有一个负值的 BigInteger
BigInteger a = new BigInteger("-173B8EC504479C3E95DEB0460411962F9EF2ECE0D3AACD749BE39E1006FC87B8", 16);
然后我想得到 BigInteger 形式的 2 的补码
BigInteger b = E8C4713AFBB863C16A214FB9FBEE69D0610D131F2C55328B641D61EFF9037848
我可以从 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 减去第一个BigInteger,但是对于任何长度的BigInteger 是否有通用的方法来计算它?
为了使这个值成为它的二进制补码,你将不得不对内容进行操作。那当然是不可能的,所以你先把内容拿出来,操作一下,然后把它们放到一个新的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
确实是二进制补码,而不仅仅是对位的重新解释。
BigInteger中有获取2的补码的方法吗? 例如:如果有一个负值的 BigInteger
BigInteger a = new BigInteger("-173B8EC504479C3E95DEB0460411962F9EF2ECE0D3AACD749BE39E1006FC87B8", 16);
然后我想得到 BigInteger 形式的 2 的补码
BigInteger b = E8C4713AFBB863C16A214FB9FBEE69D0610D131F2C55328B641D61EFF9037848
我可以从 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 减去第一个BigInteger,但是对于任何长度的BigInteger 是否有通用的方法来计算它?
为了使这个值成为它的二进制补码,你将不得不对内容进行操作。那当然是不可能的,所以你先把内容拿出来,操作一下,然后把它们放到一个新的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
确实是二进制补码,而不仅仅是对位的重新解释。