位掩码问题?

23

我有以下代码:

public static final int LIMIT_ONE = 1;
public static final int TRADEABLE = (1 << 1);
public static final int SELLABLE = (1 << 2);
public static final int STORABLE = (1 << 3);
public static final int STORABLE_IN_WH = (1 << 4);
public static final int STORABLE_IN_LEGION_WH = (1 << 5);
public static final int BREAKABLE = (1 << 6);
public static final int SOUL_BOUND = (1 << 7);
public static final int UNK9 = (1 << 8);
public static final int UNK10 = (1 << 9);
public static final int UNK11 = (1 << 10);
public static final int CAN_COMPOSITE_WEAPON = (1 << 11);
public static final int BLACK_CLOUD_TRADERS = (1 << 12);
public static final int CAN_SPLIT = (1 << 13);
public static final int UNK15 = (1 << 14);
public static final int UNK16 = (1 << 15);

我想了解如何计算出以下结果,例如:12414。我对位掩码工作原理一无所知,如果有人能给我一些提示并解释一下它是如何得出该数字的,我将不胜感激。


你想知道 << 是什么意思吗?我不明白这个问题。 - Nikita Rybak
@Nikita,从上面的集合中,我想了解它是如何生成12414位掩码并如何恢复它的。 - Prix
6个回答

38

12414在二进制中表示为:

Binary number: 1  1  0  0  0  0  0  1  1  1  1  1  1  0
-------------------------------------------------------
Bit positions: 13 12 11 10 9  8  7  6  5  4  3  2  1  0

查看哪些位是1。这些位是在位掩码中设置的标志,位掩码是通过使用按位或运算符组合标志而创建的:

bitmask = TRADEABLE | SELLABLE | STORABLE | STORABLE_IN_WH | STORABLE_IN_LEGION_WH | BREAKABLE | BLACK_CLOUD_TRADERS | CAN_SPLIT;
为了进一步解释这个问题,STORABLE = (1 << 3); 的意思是 STORABLE 等于数字 1(二进制 1,仅在第 0 位上)左移 3 位。请注意,STORABLE = Math.pow(2, 3); 是等价的。因为标志中没有任何位重叠,所以我们可以将它们全部组合成一个单独的 int,然后稍后再拆分它们。
我们可以使用按位与运算符检查标志是否存在,如果标志被设置,则返回非零值,否则返回零值:
if(bitmask & TRADEABLE != 0) {
    // This item can be traded
} else {
    // This item cannot be traded
}

我们可以这样设置、清除或切换标志:

bitmask |= TRADEABLE; // Sets the flag using bitwise OR
bitmask &= ~TRADEABLE; // Clears the flag using bitwise AND and NOT
bitmask ^= TRADEABLE; // Toggles the flag using bitwise XOR 

非常感谢,这确实是一种简便的方式来验证一个位掩码是否包含某些内容! - Prix

21

(1 << n)的表达式等价于2的n次方。

当你写(1 << n) | (1 << m)时,只要nm不同,这与(1 << n) + (1 << m)相同。因此,你可以将其视为简单的加法运算。

数字12414在二进制中表示为11000001111110,因此它是以下标志的总和(或按位OR):

TRADEABLE                1 << 1  =     2
SELLABLE                 1 << 2  =     4
STORABLE                 1 << 3  =     8
STORABLE_IN_WH           1 << 4  =    16
STORABLE_IN_LEGION_WH    1 << 5  =    32
BREAKABLE                1 << 6  =    64
BLACK_CLOUD_TRADERS      1 << 12 =  4096
CAN_SPLIT                1 << 13 =  8192
========================================
                         Total   = 12414

请注意,包含的标志对应于在右向左读取12414的二进制表示中设置的位。


1
正确,但也许他是在问如何找到存储在给定数字(例如12414)中的标志 - 他正在寻找运算符。 - Konerak
那么 (1 << 1) 的结果是2?当 n = 3,m = 4 时,(1 << n) + (1 << m) 的结果是14? - Prix
@Konerak 是的,我想知道如何将其从那个数字还原。 - Prix
1
@Mark 的回答非常好,有没有更简单的方法来验证位掩码中是否包含 BREAKABLE? - Prix
1
@价格:使用以下代码:if (n & BREAKABLE != 0) { ... }。这将测试第6位上是否设置了比特位。 - Mark Byers
1
...并编写一个isBreakable()函数,以使其在您的代码中更易读 :) - Konerak

5

a << ba的二进制位向左移动b个位置,右侧用零填充新位。 1 << n 等同于一个只有第n位(从右边开始数第0位)为1的整数,即2n

12414的二进制表示是11000001111110。因此,它是通过下面列出的常量求和得到的。您可以通过查看从右边开始数第1位设置了,因此TRADEABLE被“设置”;第7位没有设置(为0),因此SOUL_BOUND未被“设置”来解决这个问题。请注意,位数与(1 << n)的声明值相关联。

TRADEABLE
SELLABLE
STORABLE
STORABLE_IN_WH
STORABLE_IN_LEGION_WH
BREAKABLE
BLACK_CLOUD_TRADERS
CAN_SPLIT

你真快!比我先完成了。 - Mike Dunlavey

0
在二进制中,12414是11000001111110。LIMIT_ONE在二进制中是1,而位移运算符<<将零向左移动并在右侧填充零。因此,tradeable在二进制中是10,以此类推,直到unk16,最终为1000000000000000。现在,使用按位或将这些值组合在一起,基本上在每个位置上放置一个1,其中至少有一个操作数在该位置上具有一个1(在大多数语言中使用管道运算符'|')。
例如:
100 | 10 = 110

因此,要得到12414,您需要对以下变量进行按位OR运算:unk16、unk15、tradeable、selleable、storeable、storeable in wh、storeable in legion wh和breakable。每个变量中不同位置上的1的组合为11000001111110的二进制数,转换为十进制即为12414。

这可能是最简单的解释方式,如果您想了解更多信息,可以阅读有关按位运算符以及数字的二进制表示方法。

要找出数字12414具有哪些标志,可以使用「&」(按位AND) 运算符并进行零检查。例如:

6 & 2 = 2 (110 has a 1 on the same position as 2, which is 010)
6 & 1 = 0 (110 does not have a 1 on the same position as 1, which is 001)

0

我不理解问题“如何计算以得出以下结果”。(计算什么?)

要理解的主要事情是,所有计算机值都以二进制形式存储。任何数字都将是0和1位的组合。有些数字只有一个1位。

http://en.wikipedia.org/wiki/Mask_(computing)


0

我的猜测是你会取一个数字,比如你的例子12414,并找出它包含哪些属性。

例如,由于12414在二进制中为11000001111110,因此无论它连接到什么,在与掩码进行与运算时都是可交易的,因为这个数字与掩码进行与运算将在第二位上给你一个1。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接