C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: C#の&演算子について


(過去ログ 130 を表示中)

[トピック内 10 記事 (1 - 10 表示)]  << 0 >>

■77084 / inTopicNo.1)  C#の&演算子について
  
□投稿者/ EDF (30回)-(2015/09/09(Wed) 21:31:27)

分類:[C#] 

C#のソースコードを読んでいたら
if( (i & 0x01) == 0x00 )
というコードがでてきました。
調べるとこれはビット演算子とかいうものだそうですが、
ここでこれを用いるいみがよくわかりません。

自分の解釈
二つの16進数の桁ごとにどちらも1で一致するかをしらべてどちらも1だった
とき新しできる数字の対応する桁を1にする

自信がないのでおしえてください

引用返信 編集キー/
■77086 / inTopicNo.2)  Re[1]: C#の&演算子について
□投稿者/ Azulean (517回)-(2015/09/09(Wed) 23:08:34)
2015/09/09(Wed) 23:09:03 編集(投稿者)

2 進数について調べてみると良いでしょう。
以下は左が 10 進数、右側 2 進数の一例です。

0 = 000
1 = 001
2 = 010
3 = 011
4 = 100

& 演算子、つまり論理積は 2 進数で同じ桁を見た時、両方とも 1 だったときは結果のその桁も 1 になり、どちらかまたは両方が 0 のときは結果のその桁も 0 になります。
今回の & 0x01 は 1 の 2 進数パターン 001 との論理積なので、結果は以下のようになります。

0 → 000 & 001 → 000 == 0
1 → 001 & 001 → 001 != 0
2 → 010 & 001 → 000 == 0
3 → 011 & 001 → 001 != 0
4 → 100 & 001 → 000 == 0

結論から言えば、(i & 0x01) == 0 は偶数かどうかを判定します。
引用返信 編集キー/
■77087 / inTopicNo.3)  Re[1]: C#の&演算子について
□投稿者/ shu (778回)-(2015/09/09(Wed) 23:18:16)
No77084 (EDF さん) に返信
> C#のソースコードを読んでいたら
> if( (i & 0x01) == 0x00 )
> というコードがでてきました。
> 調べるとこれはビット演算子とかいうものだそうですが、
> ここでこれを用いるいみがよくわかりません。
>
0x01をビット列(2進数)で表現すると

00000001
となります。
iをビット列で表したとき
ZZZZZZZ0  ・・・(a)
または
ZZZZZZZ1 ・・・(b)
となります。(Zは異なる任意の0または1)

i & 0x01は
(a)の場合00000000になるし
(b)の場合00000001になります。
つまり&演算子は後の数をビット列にしたとき1になる部分を前のビット列より抽出するような
計算になります。0,1を用いたビット列で各ビット毎に意味を持たせたような場合に
特定の場所のビット情報を取得するのによく利用します。
今回の場合は一番右のビットが0ならi & 0x01が0x00となるので条件に一致することになります。


引用返信 編集キー/
■77088 / inTopicNo.4)  Re[2]: C#の&演算子について
□投稿者/ ぶなっぷ (48回)-(2015/09/10(Thu) 09:48:11)
2015/09/10(Thu) 09:48:23 編集(投稿者)
ロジック的な意味は先のお二方が解説されていますので、私の方は実用上の意味を
お話しさせていただきます。

よく使われるのは、各ビットを特定の処理や状態に割り当てて、そのON/OFF状態の
設定に使うことです。

以下は半分ギャグのサンプルですが(笑)
このようなenumがあるとして、
  enum Live
  {
     Eat   = 0x01,  // 食う
     Sleep = 0x02,  // 寝る
     Play  = 0x04,  // 遊ぶ
     Work  = 0x10,  // 働く
  };

こんな感じで、各ビットを各処理に見立てて、そのON/OFFで処理のあり/なしを
決定します。

static void Main(string[] args)
{
    // 寝る間を惜しんで遊ぶ人
    var PlayfulHuman = new Human(Live.Eat | Live.Play);
    PlayfulHuman.LiveSimulation();

    // 食って寝るだけが楽しみの人
    var CorruptHuman = new Human(Live.Eat | Live.Sleep);
    CorruptHuman.LiveSimulation();

    // ま、どっちも働かないのね(^^;)
}

public class Human
{
    private Live Live;

    public Human(Live Live)
    {
        this.Live = Live;
    }

    public void LiveSimulation()
    {
       if((Live & Live.Eat) > 0)      // &はこんな感じで使う
       {
           Eat();   // 食う
       }
       if((Live & Live.Sleep) > 0)
       {
           Sleep(); // 寝る
       }
       if((Live & Live.Play) > 0)
       {
           Play();  // 遊ぶ
       }
       if((Live & Live.Work) > 0)
       {
           Work();  // 働く
       }
    }
}

働かざる者食うべからずなら、こんな感じ
    public void LiveSimulation()
    {
       if((Live & Live.Eat) > 0)      // &はこんな感じで使う
       {
           if((Live & Live.Work) == 0)
           {
               MessageBox.Show("働かざる者食うべからず");
           } else {
               Eat();  // 食う
           }
       }
       : (以下略)
    }

引用返信 編集キー/
■77089 / inTopicNo.5)  Re[3]: C#の&演算子について
□投稿者/ とっちゃん (303回)-(2015/09/10(Thu) 10:37:35)
とっちゃん さんの Web サイト
No77088 (ぶなっぷ さん) に返信
> if((Live & Live.Eat) > 0) // &はこんな感じで使う
> {
> Eat(); // 食う
> }
ここだけ。

BIT演算する場合は、最上位ビットの符号が影響するので == 0 または != 0 で比較することをお勧めします。

なので、上記のような場合は

if( (Live & Live.Eat) != 0 )

というように、意識的に boolean 的に処理するようにしたほうがいいですよ。


引用返信 編集キー/
■77090 / inTopicNo.6)  Re[3]: C#の&演算子について
□投稿者/ 魔界の仮面弁士 (487回)-(2015/09/10(Thu) 11:05:49)
No77088 (ぶなっぷ さん) に返信
> このようなenumがあるとして、
>  enum Live
>  {
>   Eat  = 0x01, // 食う
>   Sleep = 0x02, // 寝る
>   Play = 0x04, // 遊ぶ
>   Work = 0x10, // 働く
>  };

本題からは少し外れますが、上記のように「ビットフラグ」として管理される列挙体には、
FlagsAttribute を付与するのが慣わしとなっています。具体的にはこういう定義になりますね。


[Flags]
enum Live
{
 Eat  = 0x01, // 食う
 Sleep = 0x02, // 寝る
 Play = 0x04, // 遊ぶ
 Work = 0x10, // 働く
};

// -----------------

 Live hate = Live.Work;
 Console.WriteLine(hate.ToString("G"));

 Live love = Live.Eat | Live.Sleep | Live.Play;
 Console.WriteLine(love);

[Flags] の属性指定がある場合には、それぞれ "Work" および "Eat, Sleep, Play" と表示されますが、
[Flags] の属性指定が無い場合には、それぞれ "Work" および "7" と表示されることになります。


参考情報:FlagsAttribute を付与するかどうかのガイドラインとして。
http://smdn.jp/programming/netfx/enum/1_flags/


> if((Live & Live.Eat) > 0) // &はこんな感じで使う
既に指摘されていますが、ここは > では無い方が良いですね。

ちなみに .NET 4 以降においては、上記を
 if (Live.HasFlag(this.Live))
と書けるようになっています。
引用返信 編集キー/
■77092 / inTopicNo.7)  Re[4]: C#の&演算子について
□投稿者/ furu (23回)-(2015/09/10(Thu) 12:04:20)
No77090 (魔界の仮面弁士 さん) に返信
>
> ちなみに .NET 4 以降においては、上記を
>  if (Live.HasFlag(this.Live))
> と書けるようになっています。

魔界の仮面弁士さん
  if (Live.HasFlag(Live.Eat))
ではないのですか?

if (Live.HasFlag(this.Live))
はどういうことが起きるのでしょうか?
引用返信 編集キー/
■77093 / inTopicNo.8)  Re[5]: C#の&演算子について
□投稿者/ 魔界の仮面弁士 (488回)-(2015/09/10(Thu) 12:14:18)
No77092 (furu さん) に返信
> 魔界の仮面弁士さん
>   if (Live.HasFlag(Live.Eat))
> ではないのですか?

その通りですね。furu さん、フォローありがとうございます。
引用返信 編集キー/
■77094 / inTopicNo.9)  Re[5]: C#の&演算子について
□投稿者/ shu (779回)-(2015/09/10(Thu) 12:25:33)
No77092 (furu さん) に返信

> if (Live.HasFlag(this.Live))
> はどういうことが起きるのでしょうか?

条件結果が必ず真になると思います。
ここのLiveはprivate変数のLiveなので
Liveもthis.Liveも同じもの。


> private Live Live;
そもそもこういう定義自体が良くないですね。
引用返信 編集キー/
■77095 / inTopicNo.10)  Re[6]: C#の&演算子について
□投稿者/ ぶなっぷ (49回)-(2015/09/10(Thu) 13:59:24)
いろいろ話が盛り上がっていますね(^^)
コーディングの善し悪しの話はいろいろな意見が出てきて面白いです。

FlagsAttributeの[Flags]については私自身忘れがちですが、確かに[Flags]を
付けた方がいいですね。
なぜなら、動作が変わるからです。
  Trace.WriteLine(Live.Eat | Live.Sleep);
としたとき、[Flags]があると、
  Eat, Sleep
と表示されるため分かり易いからです。
[Flags]が無いと、
  3
の表示になっていまい、デバッグの時は不便です(^^;)

こちらに関しては、いろんな意見がありそうですね。
> BIT演算する場合は、最上位ビットの符号が影響するので == 0 または != 0
> で比較することをお勧めします。

すでに出てきている
  Live.HasFlag()
や、人によっては、
  if((Live & Live.Eat) == Live.Eat)
だと言う人もいるでしょう。

最上位ビットまで使うかどうかはさておき、不慮の事故を防ぐためには確かに
こうした方が良さそうです。今後、私も > 0 はやめたいと思います(^^)

ただ、
>> private Live Live;
>そもそもこういう定義自体が良くないですね。
については、好みの問題であり、善し悪しを語るものではないと考えます。
定義に対して、実体が1つしか無い場合には、無理に定義名と実体名を変える
より分かりやすいと思うからです。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -