【问题标题】:How to get the 2's complement value of a BigInteger of arbitrary length如何获得任意长度的 BigInteger 的 2 的补码
【发布时间】:2016-12-19 11:32:57
【问题描述】:

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

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

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

BigInteger b = E8C4713AFBB863C16A214FB9FBEE69D0610D131F2C55328B641D61EFF9037848

我可以从 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 中减去第一个 BigInteger 以获得第二个 BigInteger,但是是否有通用方法来计算任何长度的 BigInteger?

【问题讨论】:

  • 对不起,我没有答案,但你到底在用这个做什么?
  • 我们在 Android 和 iOS 上都遵循一个协议。在 iOS 中,BIGNUM 产生一个 +ve 数字,但在 Android 中,BigInteger 显示一个 -ve 数字(2 的补码)。我们需要匹配这两个值以进行计算。
  • 你为什么要使用 BigInteger 呢?我认为这更多是协议解析器的问题。我建议您编辑您的问题并添加信息和代码,说明您收到的数据、解析方式以及之后的处理方式。
  • 错误,BigInteger.negate()?这是一个谜吗?
  • BigInteger.negate() 只是改变符号但值没有改变。

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


【解决方案1】:

使这个值成为二进制补码,您必须对内容进行操作。这当然是不可能的,所以你先把内容拿出来,操作它们,然后把它们放到一个新的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,那么如果 BigInteger 已经是正数,则不要调用 twosComplement(),或者在 original 是正数时让它返回。以上会将 -ve 转换为 +ve ,反之亦然。
  • 谢谢 Rudy,我已经为 -ve BigIntegers 添加了以下条件,它工作正常。 if (b.compareTo(BigInteger.ZERO)
猜你喜欢
  • 2015-07-28
  • 1970-01-01
  • 2015-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-06
  • 2021-09-26
  • 2010-12-06
相关资源
最近更新 更多