【Java相关】二进制角度计算~0x99^0x66

来源:互联网 发布:淘宝客服每日知识总结 编辑:程序博客网 时间:2024/05/22 13:35

今天碰到一个取反符号,在之前代码中从来没用过,然后有个小哥提出这个计算题,心血来潮就算一算,顺便记录一下。

且以Java中int类型为例解释算式。

  • 0x99 十六进制数 99
  • 0x66 十六进制数 66
  • ~ 按位取反
  • ^按位异或

    int类型为32位,其中最高位是符号位,0为正数,1为负数,负数使用补码表示。补码=反码+1。

0x99的二进制表示:
0000 0000 0000 0000 0000 0000 1001 1001
按位取反后:
1111 1111 1111 1111 1111 1111 0110 0110
(此时看最高位为1,发现这是一个负数,如何将这个负数换为十进制且容后再看)

0x66的二进制表示:
0000 0000 0000 0000 0000 0000 0110 0110

将这两个二进制数做异或运算,需要先明白异或的运算法则:同得0,异得1。
数1:1111 1111 1111 1111 1111 1111 0110 0110
数2:0000 0000 0000 0000 0000 0000 0110 0110
结果:1111 1111 1111 1111 1111 1111 0000 0000

可以看到结果是0xFFFFFF00。

至于这个数对应十进制是几,需要换算一次。
从最高位可以看到这是负数,所以这个二进制码是补码,先确定一个负号,然后再来计算这个数的绝对值。
补码和原码的关系是,原码取反+1=补码,补码取反+1=原码。
先来按前一个关系计算:
补码:1111 1111 1111 1111 1111 1111 0000 0000
减一:1111 1111 1111 1111 1111 1110 1111 1111
取反:0000 0000 0000 0000 0000 0001 0000 0000

然后按后一个关系计算:
补码:1111 1111 1111 1111 1111 1111 0000 0000
取反:0000 0000 0000 0000 0000 0000 1111 1111
加一:0000 0000 0000 0000 0000 0001 0000 0000

可以看到两种计算方法结果是相同的,这也是计算机中补码和原码的意义所在,二者存在这种关系使得换算思维变得一致,而非常见的加减运算的逆运算关系。

最后可以看到这个数的绝对值为2的8次方,即256。十六进制表示是0x100,因此这个数可以写作-0x100。

那么,~0x99^0x66 = 0xffffff00 = -0x100 = -256。

接下来代码验证:

public static void main(String[] args) {    int a = 0x99;    int b = 0x66;    int c = ~a^b;    System.out.println(Integer.toHexString(c));    System.out.println(c);    int d = 0xffffff00;    System.out.println(d);    int e = -0x100;    System.out.println(e);}

附图输出结果:
这里写图片描述

有更快的计算方式请留言,本喵比较老实,不会技巧。

谢谢阅读。