b&0xF 与 b是什么关系

今天同事看到一行代码

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,相异为0

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

8 & 1

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

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

计算,相同的为 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。我们可以利用这个来判断奇偶(运算速度比取余快)

你可能感兴趣的:(Java)