转载自: https://blog.csdn.net/u013513053/article/details/104674801/
今天同事看到一行代码
if ((d2[i] & 0x0F) == 0x0F || (d2[i] & 0xF0) == 0xF0){
//省略
}
然后就很奇怪这个运算,一个数值与上 0x0F,判断是否等于0x0F。那么这个数值与 0xF不就是数字本身么?为啥要多此一举呢?我试验了一下,的确
1 & 0x0F = 110 & 0x0F = 1015 & 0x0F = 15
这么看的确是很困惑,如果这样的话,为啥不直接判断 d2[i] == 0x0F 这样呢?
负数操作
我印象中好像我也这么干过,但是太久远了一直想不起来为啥。我就去查资料。但是百度出来的也没说出所以然,我忽然想了起来,负数与之后也是这样么?
我用-1做实验,果然结果是不一样的。-1 & 0x0F = 15-10 & 0x0F = 6-15 & 0x0F = 1
这是为什么呢?java中的几个规则:
Java中byte的大小是8bits,int的大小是32bits,byte的范围是[-128,127],int的范围是[-231,231-1]。
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 = 017 & 0x0F = 1
这里又得说一下 & 操作符的意思。很简单,就一句话
全部为1则为1,有一位0则为0
这里是二进制的位,每一位进行比较操作,全部为1则为1,有一个为0则为0。这么说可能不太明白,举个例子就好了
8 & 1
转换为二进制(二进制转换就不多说了)1000&1
补位,不足的前面补0。这里1前面需要补足1000&0001
计算,全部为1的为 1 ,有0的为 0每一位分别是1&0 = 00&0 = 00&0 = 00&1 = 0最终为0000结果为 0
这是原理,但是相信解释原理即使明白了,实际运用也是困难的。谁闲着没事转二进制计算?数字小还可以,要是数字大呢?算去吧
这里我们找找有没有简便的方法或者规律,我们不妨多些几个看看
1&1 = 12&1 = 03&1 = 14&1 = 0
2&2 = 23&2 = 24&2 = 05&2 = 06&2 = 27&2 = 28&2 = 09&2 = 0
3&3 = 34&3 = 05&3 = 16&3 = 27&3 = 38&3 = 09&3 = 110&3 = 2
我们可以发现一些结论
一个数&自身等于这个数自身
奇数&1等于1,偶数&1 =0。我们可以利用这个来判断奇偶(运算速度比取余快)
清零。如果想将一个单元清零,即使其全部二进制位为0,只要与一个各位都为零的数值相与,结果为零。
取一个数中指定位方法:找一个数,对应X要取的位,该数的对应位为1,其余位为零,此数与X进行“与运算”可以得到X中的指定位。例:设X=10101110,取X的第4位,用 X & 0000 1111 = 0000 1110即可得到;还可用来取X的2、4、6位。