已存在標誌DEFS:容易算法使用標誌
flag1=1
flag2=2
flag3=4
flag4=8
...
flagN=2^(N-1)
flag=flag1+flag2+...+flagN
如果flagI
沒有設置,它的EQ 0
我有flag
。哪種方法可以輕鬆檢查,例如定義了flag2
?
已存在標誌DEFS:容易算法使用標誌
flag1=1
flag2=2
flag3=4
flag4=8
...
flagN=2^(N-1)
flag=flag1+flag2+...+flagN
如果flagI
沒有設置,它的EQ 0
我有flag
。哪種方法可以輕鬆檢查,例如定義了flag2
?
什麼的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,這可能是由持有unsigned int
在C/C++):
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)
+-------------------------------+
Boolean isSet (flags, flagN){
Return (flags & flagN) != 0;
}
旗作爲國旗載體,flagN旗要檢查
注意,在每個標誌只有一個位被設置爲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
你可以用所有的標誌來做到這一點。
值得深入研究位掩碼和標誌的概念。然後你可以用你的想象力來有效地表達狀態。 (只是一個例子說明如下)
First -Define the bitmask : 0x0000001c
什麼是,當你做的面罩上的「和」操作的二進制字符串,你會得到一個非零值?
這些是您的有效標誌值。
此位掩碼有效標誌值: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並評估上述操作。
這是功課? – batbrat 2012-08-05 08:45:14
根據您的語言...移位操作'flagN = 1 <<(N-1)'比便宜的乘法或指數更便宜和快捷。 http://en.wikipedia.org/wiki/Bitwise_operation#Arithmetic_shift – klaustopher 2012-08-05 08:56:02