b&0xF 与 b是什么关系

转载自: https://blog.csdn.net/u013513053/article/details/104674801/

今天同事看到一行代码

if ((d2[i] & 0x0F) == 0x0F || (d2[i] & 0xF0) == 0xF0){
//省略
}

然后就很奇怪这个运算,一个数值与上 0x0F,判断是否等于0x0F。那么这个数值与 0xF不就是数字本身么?为啥要多此一举呢?
我试验了一下,的确

1 & 0x0F = 1
10 & 0x0F = 10
15 & 0x0F = 15

这么看的确是很困惑,如果这样的话,为啥不直接判断 d2[i] == 0x0F 这样呢?

负数操作

我印象中好像我也这么干过,但是太久远了一直想不起来为啥。我就去查资料。但是百度出来的也没说出所以然,我忽然想了起来,负数与之后也是这样么?

我用-1做实验,果然结果是不一样的。
-1 & 0x0F = 15
-10 & 0x0F = 6
-15 & 0x0F = 1

这是为什么呢?
java中的几个规则:

  1. Java中byte的大小是8bits,int的大小是32bits,byte的范围是[-128,127],int的范围是[-231,231-1]。

  2. Java中数值的二进制是采用补码的形式表示的。

byte 的长度是有限的,最大是127,那么对于十六进制的FF怎么办呢?我们经常要存储十六进制的数字,而十六进制一位最大值FF 就是255,byte肯定超限了。java也是很贴心的给出了解决,0-127直接表示就可以,128也就是 0x80,就用负数表示,值为-128。值从负值递增,129就是-127,130就是-126依次类推。,-1 到最大 255,也就是0xFF。

那么从byte中取出来16进制数怎么办,那就用byte 值与上 0xFF。注意这里是0xFF。

这样就可以理解了,-1其实不是-1,而是十六进制0xFF。所以用-1&0x0F的结果就相当于 0xFF&0x0F。

然而结束了么?并没有

& 操作

上面例子测试只到了15,我们继续把数值调大试一下
16 & 0x0F = 0
17 & 0x0F = 1

这里又得说一下 & 操作符的意思。很简单,就一句话

全部为1则为1,有一位0则为0

这里是二进制的位,每一位进行比较操作,全部为1则为1,有一个为0则为0。这么说可能不太明白,举个例子就好了

8 & 1

转换为二进制(二进制转换就不多说了)
1000&1

补位,不足的前面补0。这里1前面需要补足
1000&0001

计算,全部为1的为 1 ,有0的为 0
每一位分别是
1&0 = 0
0&0 = 0
0&0 = 0
0&1 = 0
最终为
0000
结果为 0

这是原理,但是相信解释原理即使明白了,实际运用也是困难的。谁闲着没事转二进制计算?数字小还可以,要是数字大呢?算去吧

这里我们找找有没有简便的方法或者规律,我们不妨多些几个看看

1&1 = 1
2&1 = 0
3&1 = 1
4&1 = 0

2&2 = 2
3&2 = 2
4&2 = 0
5&2 = 0
6&2 = 2
7&2 = 2
8&2 = 0
9&2 = 0

3&3 = 3
4&3 = 0
5&3 = 1
6&3 = 2
7&3 = 3
8&3 = 0
9&3 = 1
10&3 = 2

我们可以发现一些结论

    1. 一个数&自身等于这个数自身
    2. 奇数&1等于1,偶数&1 =0。我们可以利用这个来判断奇偶(运算速度比取余快)
    3. 清零。如果想将一个单元清零,即使其全部二进制位为0,只要与一个各位都为零的数值相与,结果为零。
    4. 取一个数中指定位
      方法:找一个数,对应X要取的位,该数的对应位为1,其余位为零,此数与X进行“与运算”可以得到X中的指定位。
      例:设X=10101110,
      取X的第4位,用 X & 0000 1111 = 0000 1110即可得到;
      还可用来取X的2、4、6位。
原文地址:https://www.cnblogs.com/kate7/p/14144668.html