2012-07-03 49 views
12

我有三個代表位的bool值。我想有形式從三個布爾值創建一個整數作爲C++中的位

true true true = 7 
false true false = 2 

的整數我有

int val = 4*boolVal1 + 2*boolVal2 + boolVal3; 

有另一種方式,也許更簡單?

+1

只是fyi,不應該「真實的真實」導致7?否則,所有的公式到目前爲止是錯誤的... – SinisterMJ

+2

'int val = 4 * boolVal1 + 2 * boolVal2 + boolVal3;'將給出7當你有真正的真正不是8 –

+0

正確的,我剛貼錯了。 Thx糾正! – tzippy

回答

27

您可能會發現更加清晰使用位運算符,而不是乘法和加法:

比乘法和bitshifting
int val = (boolVal1 << 2) | (boolVal2 << 1) | boolVal3; 
4

其他,你也可以使用一個枚舉來記錄的關係。通常不值得努力,但只是爲了完整...

enum Encoding 
{ 
    Flag3 = 1,  NotFlag3 = 0, 
    Flag2 = 1 << 1, NotFlag2 = 0, 
    Flag1 = 1 << 2, NotFlag1 = 0 
}; 

int val = (boolVal1 ? Flag1 : NotFlag1) | 
      (boolVal2 ? Flag2 : NotFlag2) | 
      (boolVal3 ? Flag3 : NotFlag3); 

爲什麼地球上你會爲此感到困擾?這只是一個更一般的說法,因此您可以稍後更改編碼值,而無需使用實際值觸及潛在分佈式代碼(例如,如果您意識到與某些文件或網絡的格式相比,你需要解析的數據,你可以將它添加到一個地方並重新編譯)。當然,最好只提供一個編碼/解碼功能,如果你添加新的標誌,你仍然需要它。

雖然有Flag1和NotFlag1可能看起來毫無意義,但通常情況下,您有像粘滯和浮動,或男性和女性互斥值的東西,並沒有特別的理由來強制客戶檢查說浮動爲!置頂或女性爲男性等。

+0

'NotFlag'在這裏不是很有幫助。如果你想知道Flag2是否被清除,你仍然會檢查'(value&Flag2)== NotFlag2'。此外,'?:'可能會產生比乘法更慢的代碼(分支與算術運算)。另外,我發現爲這樣的枚舉重載運算符'|','&','^'和'〜'很方便,因此這個類型被保留 - 我甚至有一個宏。 – krlmlr

+0

@ user946850:通常一個函數(特別是C函數)要求調用者對來自標誌的參數進行編碼,因此分佈式調用代碼 - 其中可以有任意數量和「清潔度」因此非常重要,可以或在一起標誌和「NotFlag」非常高興,不需要進行標誌測試 - 這是在被調用函數的實現中整合的步驟,更容易維護。是的,當枚舉被用作客戶端代碼中的適當值時(而不僅僅是爲了編碼參數),正確的操作符值得擁有。 –

5

或者你可以使用Horner的方法:

int val = (((boolVal1 << 1) | boolVal2) << 1) | boolVal3.

這也使得它更容易添加或刪除語句的中間變量,而無需改變所有其他係數。

但是,這可能對讀者來說不太明顯。

+1

這不是很可能很重要,但我很好奇 - 是否使用通用編譯器 - 由於在評估中有順序排列,它可能會變得更糟:知道它們的任何/所有優化器是否可以生成可以在CPU指令流水線上並行化...... –

+0

@Tony,你必須看看機器代碼,但我希望現代編譯器能夠注意到括號內沒有分支,並且相當乾淨地展開它。 –

2

如果你知道你也可以使用實現定義和位集,小端版本的存儲方式:

union foo { 
     unsigned int the_int; 
     struct { 
       unsigned int bit3:1 
       unsigned int bit2:1 
       unsigned int bit1:1 
     }; 
}; 

,然後對其進行設置:

foo.bit1 = true; 
foo.bit2 = false; 
foo.bit3 = true; 

和閱讀:

foo.the_int; 

大端版本有位反轉和大量的填充(29位,如果unsigned int是32位寬)在前面。

相關問題