2012-07-03 4 views
12

ビットを表す3つのbool値があります。私は多分より簡単な別の方法がある私はC++のビットとして3つのブール値から整数を作成

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

を持つ形で

true true true = 7 
false true false = 2 

を整数をしたいですか?

+1

ちょうどfyi、「true true true」は7になりませんか?さもなければ、これまでの数式はすべて間違っています... – SinisterMJ

+2

'int val = 4 * boolVal1 + 2 * boolVal2 + boolVal3;'真を真にしたときに真を返します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); 

なぜあなたはこれを気にしますか?実際の値を使用して潜在的に分散されたコードに触れることなく、後でEncodingの値を変更することも可能です(たとえば、ファイルやネットワークの形式解析する必要があるデータは、1つの場所に追加して再コンパイルすることができます)。もちろん、とにかく単一のエンコード/デコード機能を提供する方が良いでしょう。新しいフラグを追加する場合は、それでも必要になります。

Flag1とNotFlag1を持っているのは無意味に見えるかもしれませんが、スティッキーとフローティング、男性と女性のような相互に排他的な値があることがよくあります。 !スティッキーまたは女性として男性など。

+0

'NotFlag'sはあまり役に立ちません。 Flag2がクリアされているかどうかを知りたければ '(value&Flag2)== NotFlag2'をチェックします。さらに、 '?:'は乗算よりも遅いコードを生成するかもしれない(分岐対算術演算)。また、そのような列挙型のために '|'、 '&'、 '^'、 '〜'の演算子をオーバーロードすると便利です。 – krlmlr

+0

@ user946850:多くの場合、関数(特にC関数)は呼び出し元にフラグからパラメータをエンコードするように要求します。そのため、分散呼び出しコードは任意の量とその "清潔さ"があるため非常に重要です。ORフラグ"NotFlag"はフラグのテストを必要とせずに非常にうまくいきます。それは呼び出された関数の実装内で統合された手順であり、ずっと簡単に維持できます。そして、はい、enumがクライアントコードで適切な値として使用されているとき - パラメタをエンコードするだけでなく、適切な演算子が持つ価値があります。 –

5

それとも、ホーナー法を使用することができます!これはまた、それが簡単に変更することなく、文の途中から変数を追加または削除することができ

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; 

ビッグエンディアンバージョンのビットは反転していて、多くのパディングがあります(unsigned intは32ビット幅です)。

関連する問題