使用标志的简单算法

时间:2012-08-05 08:41:19

标签: algorithm

存在标志defs:

flag1=1
flag2=2
flag3=4
flag4=8
...
flagN=2^(N-1)

flag=flag1+flag2+...+flagN

如果flagI未设置,则为0

我有flag。哪种方法可以轻松检查,例如flag2定义了什么?

4 个答案:

答案 0 :(得分:4)

请注意,在每个标志中,只有一位设置为1,其他位为0。

flag1 = 000 ... ... 0001
flag2 = 000 ... ... 0010
flag3 = 000 ... ... 0100
// and like this

因此,如果您按位AND flag & flag2,则只有在定义flag2时结果才为非零。

r = flag & flag2;
if r != 0 then flag2 is defined

您可以使用所有标记执行此操作。

答案 1 :(得分:4)

回答你的问题

flag的范围是多少?如果它低于2 ^ 64-1,几乎每种方法都可以。

正如@taskinoor发布的那样,你应该注意到:

flag1 = 000 ... ... 0001 

flag2 = 000 ... ... 0010 

flag3 = 000 ... ... 0100

换句话说,

flag[n] = 1 << (n-1)

因此,如果要检查所有位,for循环和bitwise operation足够快,可以解决您的问题。喜欢这个(假设您可以理解 C / C ++ 并且标志小于2 ^ 32,这可以由 C / C ++ 中的unsigned int保存:

void check(unsigned int flag)
{
  for (int i = 0; i < 32; ++i)
    if ((flag & (1 << i)) != 0)
      printf("flag%d defined!\n", i+1);
}

它是O(k),其中k是二进制中flag类型的长度。对于unsigned int,它是O(32)= O(1),几乎是在恒定时间内。

如果您只想计算定义了多少个标志:

我不知道你的目的是什么。如果您只想计算定义的标志数量且flag小于2 ^ 64,则以下方法非常棒(假设unsigned int也是如此):

unsigned int count_bit(unsigned int x)
{
  x = (x & 0x55555555) + ((x >> 1) & 0x55555555);
  x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
  x = (x & 0x0F0F0F0F) + ((x >> 4) & 0x0F0F0F0F);
  x = (x & 0x00FF00FF) + ((x >> 8) & 0x00FF00FF);
  x = (x & 0x0000FFFF) + ((x >> 16)& 0x0000FFFF);
  return x;
}

如果你拨打count_bit(1234567890),它将返回12。

让我解释一下这个算法。

此算法基于Divide and Conquer Algorithm。假设有一个8位整数213(二进制11010101),算法就像这样(每次合并两个相邻块):

+-------------------------------+
| 1 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |  <- x
|  1 0  |  0 1  |  0 1  |  0 1  |  <- first time merge
|    0 0 1 1    |    0 0 1 0    |  <- second time merge
|        0 0 0 0 0 1 0 1        |  <- third time ( answer = 00000101 = 5)
+-------------------------------+

答案 2 :(得分:0)

Boolean isSet (flags, flagN){
   Return (flags & flagN) != 0;
}

标志是标志向量,标记要检查的标志

答案 3 :(得分:0)

值得更深入地了解位掩码和标志的概念。然后,您可以使用您的想象力有效地表示状态。 (只是下面解释的一个例子)

 First -Define the bitmask :          0x0000001c 

什么是二进制字符串,当你做&#39;和&#39;在掩码上操作,你得到一个非零值?

这些是您的有效标志值。

此位掩码的有效标志值:0x0000001c,0x00000014,0x00000018,0x00000004,0x00000008,etc ..

因此,在您的应用程序中,如果您可以执行以下操作:

flagvariable |= flagvalue1  ->Enable a particular flag.  
if( flagvariable & maskvalue)   :Check if a mask is enabled  :  

然后你需要检查不同的案例:

if(flagvariable &maskvalue ==flagvalue1)    { do something}
else  
if(flagvariable &maskvalue ==flagvalue2) {do something else}    

flagvariable &= `flagvalue1  : Clear the flag  

要更清楚标志和位掩码,只需进入gdb并执行p / t并评估上述操作。