你不会还不知道按位取反运算的原理吧

引入

首先来看一个程序,分别打印4-4的取反运算结果,代码:

public static void main(String[] args) {
    System.out.println(~4);
    System.out.println(~(-4));
}

不妨思考一下结果,如果结果是-4和4的话,那请继续看下去吧.显然结果不是你想的那样,一起看下:

187MFUkJ
187MFUkJ

没错,结果就是-5和3(可不是相反数那么简单的哟),这里先告诉一个万能计算公式,要计算一个整数的取反运算,比如x,那么:

~x = -(x+1);

理解

虽然有计算公式,相信你还是跟我一样,想弄清楚为什么是这样的结果.
首先来看,~这个计算符号的定义是什么?
按照我平时的理解,当我使用~按位取反运算的时候,计算机会将操作数所对应的二进制表达式的每一个位进行取反计算,取反后所得到的值就是~按位取反的运算结果(这点没问题),但是怎么去理解呢,我们来具体分析下.

在这之前,先说一下计算机中的数据表示:
我们平时学习的二进制表示有三种形式:原码,反码和补码;
然而计算机只认识补码,原码和反码只是人们方便计算人为定义的,所以计算机中的所有计算二进制的输入输出都是补码的形式,理解到这点,就可以继续往下看了.

还是上面的程序,我们对4进行取反运算,过程如下:

  1. 4的二进制表示(补码): 0 100
  2. 计算机对它进行按位取反: 1 011
  3. 这时计算机将计算结果反馈给我们,得到的答案是: -5

可能你还是纳闷,为什么1011就得到-5了呢,不应该是-3吗?
回到刚刚说的,计算机中所有二进制输出都是补码的形式,因此1011是某一个数的补码表示形式,我们需要把他转成我们能理解的二进制:

  1. 首先看补码1 011,最高位为1,表示是一个负数,因此符号位不变,然后减1,得到反码(补码 = 反码 + 1,反之): 1 010;
  2. 将反码1 010符号位除开,按位取反得到原码: 1 101,这不就是-5了嘛.

同理,我们再看-4取反:

  1. 64的二进制表示(补码): 1 100
  2. 计算机对它进行按位取反: 0 011
  3. 这时计算机将计算结果反馈给我们,得到的答案是: 3

那为什么又是3呢?
很简单,补码0 011最高位为0,说明是正数,而正数的原码和补码是一样的,所以直接等于3.

public static void main(String[] args) {
    System.out.println(~4);
    //补码: 0 100
    //取反: 1 011
    //反码: 1 010
    //原码: 1 101 = -5
    System.out.println(~(-4));
    //1 100
    //1 011
    //补码: 1 100
    //取反: 0 011
    //原码: 0 011 = 3
}
> 欢迎关注 [码之泪殇](http://www.gongsir.club)
原文地址:https://www.cnblogs.com/gongsir/p/13335359.html