如何从数字中检索位

How to retrieve bits from number

有时我会遇到下面的代码。我相信它用于将值表示为位,它们可以组合成一个数字并在以后检索。

数字34由0100000000000100232组成。我如何在 Java 中解决这个问题?不知何故,我必须将 2 与某个变量进行比较以执行 X 并将 32 与另一个变量进行比较以执行 Y.

以下是我的一些想法的例子。

来自 DotA 模组维基。

DOTA_ABILITY_BEHAVIOR_HIDDEN               = 1 << 0, //Can be owned by a unit but can't be cast and won't show up on the HUD.
DOTA_ABILITY_BEHAVIOR_PASSIVE              = 1 << 1, //Cannot be cast like above but this one shows up on the ability HUD.
DOTA_ABILITY_BEHAVIOR_NO_TARGET            = 1 << 2, //Doesn't need a target to be cast, ability fires off as soon as the button is pressed.
DOTA_ABILITY_BEHAVIOR_UNIT_TARGET          = 1 << 3, //Needs a target to be cast on.
DOTA_ABILITY_BEHAVIOR_POINT                = 1 << 4, //Can be cast anywhere the mouse cursor is (if a unit is clicked it will just be cast where the unit was standing).
DOTA_ABILITY_BEHAVIOR_AOE                  = 1 << 5, //Draws a radius where the ability will have effect. Kinda like POINT but with a an area of effect display.
//...

所以这些 "behaviors" 被存储为 1、2、4、8、16、32 等。但是整个想法似乎能够将多种类型存储到一个 number/bytes 并稍后检索这些。我看到这样的用法:

DOTA_ABILITY_BEHAVIOR_AOE | DOTA_ABILITY_BEHAVIOR_PASSIVE

这似乎是 34。唯一会产生 34 的组合是这个 DOTA_ABILITY_BEHAVIOR_AOE | DOTA_ABILITY_BEHAVIOR_PASSIVE,我相信只要您不两次使用相同的值,以这种方式进行的每个组合都是唯一的。

那么如何从号码34中取出这两个号码呢?还有这样的用法有什么限制吗?

int x = DOTA_ABILITY_BEHAVIOR_AOE | DOTA_ABILITY_BEHAVIOR_PASSIVE

if (x & DOTA_ABILITY_BEHAVIOR_AOE == DOTA_ABILITY_BEHAVIOR_AOE)
    // do stuff

您可以添加与数据类型可以存储的一样多的单个位表示的值。

那些特殊的数字叫做位掩码,用来设置和读出二进制标志
A byteshortintlong 值因此可以包含多个这些标志。

示例:

int flag1 = 0b0000001; // 1<<0, or 1
int flag2 = 0b0000010; // 1<<1, or 2
int flag3 = 0b0000100; // 1<<2, or 4

合并标志:

int combined= flag1 | flag2;

设置标志:

combined = combined | flag3;

要取消设置标志:

combined = combined & ~flag;

检查是否设置了标志:

boolean set3 = (combined & flag3) !=0;

由于没有人回答您的具体问题:

Decimal 34 == Hex 0022 == Binary 0000 0000 0010 0010

您的价值观是

DOTA_ABILITY_BEHAVIOR_HIDDEN       = 1 << 0, // 0000 0000 0000 0001
DOTA_ABILITY_BEHAVIOR_PASSIVE      = 1 << 1, // 0000 0000 0000 0010
DOTA_ABILITY_BEHAVIOR_NO_TARGET    = 1 << 2, // 0000 0000 0000 0100
DOTA_ABILITY_BEHAVIOR_UNIT_TARGET  = 1 << 3, // 0000 0000 0000 1000
DOTA_ABILITY_BEHAVIOR_POINT        = 1 << 4, // 0000 0000 0001 0000
DOTA_ABILITY_BEHAVIOR_AOE          = 1 << 5, // 0000 0000 0010 0000

可以通过“或”运算得到十进制数 34 的两个值是

DOTA_ABILITY_BEHAVIOR_PASSIVE | DOTA_ABILITY_BEHAVIOR_AOE

关于您提到的如何取回用于获取 34 的位的部分。我将 post 和 'solution' 给出一种实现它的方法。这可能不是最好的方法。

您提到过...

DOTA_ABILITY_BEHAVIOR_HIDDEN               = 1 << 0  # 0 0 0 0 0 0 0 1
DOTA_ABILITY_BEHAVIOR_PASSIVE              = 1 << 1  # 0 0 0 0 0 0 1 0
DOTA_ABILITY_BEHAVIOR_NO_TARGET            = 1 << 2  # 0 0 0 0 0 1 0 0
DOTA_ABILITY_BEHAVIOR_UNIT_TARGET          = 1 << 3  # 0 0 0 0 1 0 0 0
DOTA_ABILITY_BEHAVIOR_POINT                = 1 << 4  # 0 0 0 1 0 0 0 0
DOTA_ABILITY_BEHAVIOR_AOE                  = 1 << 5  # 0 0 1 0 0 0 0 0

而34的二进制是0 0 1 0 0 0 1 0.

如果我们一直向左移动并检查第0个索引处的位是否已设置。

List<Integer> indx = new ArrayList<Integer>();
int count = 0;
while(n != 0) { 
    if(n & 0x1 == 1)
        indx.add(count);
    n = n >> 1;
    count++;
}

对于 34,indx 将包含 [1,5]。您可以使用它来重新创建用于形成它的位[DOTA_ABILITY_BEHAVIOR_PASSIVE, DOTA_ABILITY_BEHAVIOR_AOE]