1. 简介

反码(one's complement)是一种通过翻转数字所有二进制位来表示负数的方法。它在网络协议中常用于错误检测和校验和计算。本文将介绍在Java中计算数字反码的三种方法。

2. 使用位非运算

通过位非(bitwise NOT)操作可以直接计算反码。该运算会翻转数字二进制表示中的所有位,将0变1、1变0。

示例代码:

int calculateOnesComplementUsingBitwiseNot(int num) {
    return ~num;
}

验证结果:

int onesComplement = calculateOnesComplementUsingBitwiseNot(10);

assertEquals(-11, onesComplement);
assertEquals("11111111111111111111111111110101", Integer.toBinaryString(onesComplement));

数字10的二进制表示为"00000000 00000000 00000000 00001010"。位非运算符(~)会翻转每一位,得到"11111111 11111111 11111111 11110101"。

Java使用二进制补码(two's complement)解释有符号整数。补码中最高位表示符号(0正1负),因此该结果被解释为-11。

⚠️ 注意:

  • 正数的反码是负数,反之亦然
  • 位非运算会翻转包括符号位在内的所有位

验证负数情况:

int onesComplement = calculateOnesComplementUsingBitwiseNot(-10);

assertEquals(9, onesComplement);
assertEquals("1001", Integer.toBinaryString(onesComplement));

-10的补码表示为"11111111 11111111 11111111 11110110"。**位非运算后得到"00000000 00000000 00000000 00001001"**,即十进制9。

3. 使用BigInteger类

处理超大数字时,int类型可能不够用。此时可使用BigInteger类,其not()方法能执行位非运算:

BigInteger calculateOnesComplementUsingBigIntegerNot(BigInteger num) {
    return num.not();
}

测试示例:

BigInteger onesComplement = calculateOnesComplementUsingBigInteger(BigInteger.valueOf(10));

assertEquals(BigInteger.valueOf(-11), onesComplement);
assertEquals("11111111111111111111111111110101", Integer.toBinaryString(onesComplement.intValue()));

4. 使用异或全1掩码

另一种方法是使用位异或(^)运算配合全1掩码,此方法可精确控制位长度:

int calculateOnesComplementUsingXOROperator(int num, int bitLength) {
    int mask = (1 << bitLength) - 1;

    return num ^ mask;
}

实现原理:

  1. 通过(1 << bitLength) - 1创建指定位长的全1掩码
    • 使用左移运算(<<)生成1后接bitLength个0
    • 减1得到全1掩码(如8位时为11111111)
  2. 将输入数字与掩码进行异或运算
    • 异或操作会翻转所有位,得到反码

验证8位反码:

int onesComplement = calculateOnesComplementUsingXOROperator(10, 8);

assertEquals(245, onesComplement);
assertEquals("11110101", Integer.toBinaryString(onesComplement));

✅ 结果分析:

  • 10的8位表示:00001010
  • 异或11111111 → 11110101(245)
  • 注意:异或会翻转符号位,在补码系统中会被解释为负数

处理负数需先转换:

int calculateOnesComplementUsingXOROperator(int num, int bitLength) {
    int mask = (1 << bitLength) - 1;

    // 处理负数
    int extendedNum = num < 0 ? (1 << bitLength) + num : num;

    return extendedNum ^ mask;
}

验证-10的8位反码:

int onesComplement = calculateOnesComplementUsingXOROperator(-10, 8);

assertEquals(9, onesComplement);
assertEquals("1001", Integer.toBinaryString(onesComplement));

5. 总结

本文介绍了计算反码的三种Java实现方式:

方法 优点 适用场景
位非运算(~) 简单高效 常规整数处理
BigInteger.not() 支持大数 超大数值计算
异或全1掩码 可控位长 需指定位宽的场景

推荐优先使用位非运算,因其最简洁。当需要精确控制位长度时,异或掩码法更合适。所有示例代码可在GitHub获取。


原始标题:Calculate One’s Complement of a Number | Baeldung