位掩码的规则是什么?像0xFF vs. 0xFC

时间:2012-08-18 18:59:56

标签: java bit-manipulation bit bitmask

我正在制作一个创建程序生成的地牢的游戏,我找到了一个使用位掩码来检索房间号和门类型等内容的例子。

在该示例中,他使用位掩码从每个图块的整数中提取细节。并且整数像这样分解

0xLLSDRRET

L - is the Level Number
S - Denotes a special tile(Like Stairs)
D - is if its a door, and what type(Door, Arch, Trapped)
R - Room number
E - Flags an entrance to a room
T - Names the type of tile(Floor, Cooridor, Blocked)

在此他使用位掩码来获取例如房间号:

int[][] map = new int[40][40] 
int $ROOM_ID = 0x0000FF00;
System.out.println(map[x][y] & $ROOM_ID);

现在有了这个,如果map [x] [y]是例如0x00001200,那么输出将是1200.我知道这部分掩模。

但是在源$ ROOM_ID是ACTUALLY 0x0000FFC0并且我不明白C的作用,因为我尝试了不同的值,我似乎无法抓住C所做的,例如

0x00001200 output-> 1200
0x00001210 output-> 1200
0x00001220 output-> 1200
0x00001230 output-> 1200
0x00001240 output-> 1240
0x00001250 output-> 1240
0x00001260 output-> 1240
0x00001270 output-> 1240
0x00001280 output-> 1280
0x00001290 output-> 1280
0x000012A0 output-> 1280
0x000012B0 output-> 1280
0x000012C0 output-> 12C0
0x000012D0 output-> 12C0
0x000012E0 output-> 12C0
0x000012F0 output-> 12C0

有更多位掩码知识的人可以解释为什么0x0000FFC0& 0x000012F0 = 12C0?

3 个答案:

答案 0 :(得分:6)

你正在做的是按位算术。暂时忽略高位(因为它们都是0)并且只考虑两个十六进制值0xFFC00x12F0。然后bitwise and的工作原理与基数10中的乘法完全相同。它在位级别上看起来像这样:

0xFFC0 = 1111111111100000

&安培;

0x12F0 = 0001001011110000

然后等于0001001011100000 = 0x12F0

转换为十六进制二进制的技巧就是这个。每两个十六进制数字是一个字节(即8位)。例如,0xFF是单个字节。因此,您可以通过简单地为每个十六进制数字(即0xF (base-16) = 1111 (base-2) = 15 (base-10))写入位值将其转换为二进制表示。由于我们知道每个字节总是精确为8位,因此每个十六进制数字都会转换为自己的4位二进制表示。然后,您只需要记住十六进制值0000(0)到1111(F)的二进制表示,并适当地替换它们。诀窍在两个方向都有效。

就位掩码而言,这对于从位向量中提取值非常有用。位向量(通常)是一种简单的数据类型(即intchar等)。然后,每个特定位表示要启用或禁用的值类型。因此,如果我有一个位向量(char =单字节,例如,考虑bitvector的这种数据类型)0x01并且我的最低位表示门已启用,则此位向量有一个门。如果我的位向量值为0x02,则表示没有启用门(但在0x03中有一扇门)。为什么是这样?您需要始终查看基础二进制表示以完全理解位向量/位掩码。

0x01 = 000000010x02 = 000000100x03 = 00000011

如您所见,在第一个和第三个值中,设置了最低位。但是,在第二个值中,设置第二个最低位,但不是最低位。但是,您可以使用此第二个值来表示另一个属性(尽管出于示例的目的,第二个值中没有门)。

然后注意,从0x010x01 & 0x01 = 10x02 & 0x01 = 0 0x03 & 0x01 = 1开始,从上面格式化的位向量检索门的相应位掩码(巧合)将是{{1}} ,返回二进制表示并乘以)

答案 1 :(得分:5)

注意二进制文件,而不仅仅是十六进制文件。十六进制中的C十进制为12,二进制为1100; F是二进制的1111。所以

F& 1 == 1,F& 2 == 2,C& F == C,0& 0 == 0。

答案 2 :(得分:1)

0xF全部为1位:1111任何值和0xF的按位 AND 是相同的值。换句话说,在给定位置中带有0xF AND 会保留来自另一个操作数的位。

因此,在0x0000FFC0 & 0x000012F0中,F数字会保留相应的数字:

0xF & 0x1 = 0x1
0xF & 0x2 = 0x2
0xC & 0xF = 0xC

类似地:

0xFFC0 & 0x12F0 = 0x12C0

您可能知道,任何值的按位 AND 00。因此,像0x0000FF00这样的结构用于保留第二个最低有效字节。

0xFFC0的用法实际上取决于其余代码如何使用该最低有效字节。在标志的解释中,最低有效字节的上半部分记录为:房间的入口。在System.out.println(map[x][y] & $ROOM_ID);中,这一点很重要。

0xC是二进制的1100,因此通过在0xC0掩码中包含0xFFC0,代码也会尝试保留最不重要的两个最重要的位 - 最右边 - 字节。请注意,在这两个位上,您可以精确编码 4 值。如果游戏是2D游戏,每个房间都是Zork风格的广场,那么这个游戏设计与4个罗盘点上的入口相匹配。

至于 bitmasks的规则,从wiki article开始你可能会做得更糟:它很好地涵盖了基础知识。最终这都是boolean algebra