C#初心者の質問:And演算の使用について

このQ&Aのポイント
  • C#初心者がAnd演算を使用する場合の検討ポイントやメリット・デメリットについて、詳しい方に教えていただきたいです。
  • C#初心者がif文を使用せずにAnd演算を使用することの意義や適切な使いどころについて、経験のある方からアドバイスをいただきたいです。
  • C#初心者が複雑なif文を簡潔にまとめるため、And演算の使用を検討しているのですが、実際にメリットがあるのかどうかわからないため、知識のある方にアドバイスをいただきたいです。
回答を見る
  • ベストアンサー

これはAnd演算に変えてよいか?

 こんにちは。c#初心者です。今回はcで共通する部分(のはず)なのでc#でなくても回答できると思います。  最初はこういうコードを書いていました。 (a, b, cはint、switchOnはbool値です) int value; if ( switchOn ) value = a + b + c; else value = a + b; これを (a, b, c, maskはint。またmaskは0または111……111) int value = a + b + (c & mask); のようにifを使わない形にしてもいいのでしょうか?  この部分は今後とも変更・メンテナンスの必要が特になく、他のクラスの中に埋め込まれるクラスのメソッドで、特に第三者が見る事・必要もほとんど無く(もとい、チームとかありませんから)、可読性が重要視される訳ではないのですが、速度が重視される訳でもないんですね。  とりあえず、後者のほうを選んでも、特にデメリットはないのですが(かといってメリットもあまり無いのですが)、使えるなら予備知識になると思い、質問させていただきました。  どなたか詳しい方、いらっしゃいましたら教えていただけませんか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

やってもいいけどややこしくするだけ損かと。 僕なら int value = a + b + (swichOn ? c : 0); かしら。

koumei000
質問者

お礼

 回答ありがとうございます。  3項演算も念頭にはありましたが、投稿するのはifだけでいいかなと。  まあ、ややこしくなるだけで、アセンブラでもしない限り無用の長物なんでしょうが、知識はあっても困らないということで。  こんな事に付き合ってください、ありがとうございました。

その他の回答 (3)

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.4

「昨日の自分は今日とは別人」という言葉もありまして。 メンテナンス性は、なにより自分のためだったりします。 > int value = a + b + (c & mask); このmaskを決定する際に if( switchOn ) { mask=~ 0 ; }else{ mask=0; } などとやっているなら、valueの計算でだけifを避ける意味がないですよね。 この手法が有効なのは、 int に対してだけで、double等には使えませんよね。 アセンブリまで考えると、コンパイラの最適化の設定や性能、C#ならCLI自体の性質等、いろんな要素があって、メリットがあるかどうか単純に判断できません。 「難読」というデメリットを受け入れてまで導入するメリットは無いように思います。 // 難読そのものが目的でない限り

koumei000
質問者

お礼

 回答・ご指摘ありがとうございます。 > などとやっているなら、valueの計算でだけifを避ける意味がないですよね。  他の方の回答に書かせていただいているのですが、maskはifを使わずに設定します。それと、またしても忘れていたのですが、ローカル変数でも、引数(あれっ? 引数って、ローカル変数の一種?)でもなく、privateなフィールド変数です。  TurnSwithOn(), TurnSwithOff()メソッドなどを用いて変更します。 > 「昨日の自分は今日とは別人」  ちょっと違いますが、「一週間後の自分のコードは他人のコード」という話を聞いた事があります。さすがに、そこまで多量のコードは書いていないので一週間は自分にとって大げさですが、一ヶ月触っていなかったコードを触ったときのギャップとショックと読めなさには驚きました(ショックと驚きって重複しているような)。  それからは基本的にオープンソースとして他人に見せるつもりで書いています。あと、「コードがドキュメントだ」という他称人間コンパイラさんの言葉に感銘を受けたので、(他人の見そうなところは)コメントなしでも十分に読めるようにはしています。  といいつつ、時々、(他人が見ない部分、それもあんまりパフォーマンスに影響しそうに無い部分で)極限チューニングに拘ってみたくなったりで、葛藤に苦しんでいます。  とりあえず、こんなつまらない事に付き合ってくださいありがとうございました。

回答No.2

 回答者1さんの仰る通り3年後に見て理解し難い、追跡し難いコードは避けるべきだと思います。  私なら  value = a+b;  if( switchOn ) value += c;  ですね。  boolean の switchOnの違いでcを加算するかしないかが決まるという事が一目瞭然です。

koumei000
質問者

お礼

 回答・ご指摘ありがとうございます。  確かにそうなのですが、とりあえず、c#にはプロパティがあるので、 private const int FullMask = (2進数で111……111); public bool SwitchIsOn { get { return mask == FullMask; } } public bool SwitchIsOff { get { return mask == 0; } } にするか、または、 public bool GetSwitchIsOn { return mask == FullMask; } public bool GetSwitchIsOff { return mask == 0; }  こんな感じにすれば、maskが0のとき、スイッチオンで、maskが111……111のときにスイッチオフだと一応分かるので、理解にそんなには苦労しないと思います(c#っていうと、どんどん極限パフォーマンスから遠ざかるなぁ)。  まあ、今後アセンブラみないなことはしないと思うのですが予備知識ということで。  こんなつまらない事に付き合ってください、ありがとうございました。

  • wormhole
  • ベストアンサー率28% (1619/5653)
回答No.1

悪くということはないですけどマスクだと対象となる値の一部を取り出すみたいな気がするのであまり使わなそうな。 どちらかといえば三項演算子使うんじゃないでしょうか(if使うのと変わりないけど) それにmaskの値は結局switchOnで切り替えたりしませんか?

koumei000
質問者

お礼

 回答ありがとうございます。  まあ、普通そういう回答になりますよね。言い忘れていたのですが、アセンブラとかの場合につかえるかな~と思い、質問してみました。  あと、maskの値は、今実際にswitchOnの変数を使う方法でやっているように、SwitchOn()/SwitchOff()見たいなメソッドで変更するつもりだったので、switchOnという変数は現れません。  あと、maskを使うにしても、もう少しいいネーミングを検討する予定です(思い立ったがなんとやらで、考える前に投稿したせいで命名してなかったもんで)。例えば、switchMaskみたいに(そのまんまですが)少しは分かりやすいものにはする予定です(使うタイミングなんてあるかどうか分かりませんが)。

関連するQ&A

  • 複雑な条件の書き方

     こんにちは。c#初心者です。(今回の質問はcに近い言語ならどれでも大差ないと思います)  複雑な条件を使って処理を分岐する場合、 if ( A || (B && (C || D || E)) && F) // A~Fは条件 else  のようになったりすることもあると思いますが、それがさらに複雑化して if ( value1 < A || (B && ( (value1 = values[index]) == C || D || E)) && (value1 = values[value2]) == F ) else ( A~Fはフィールド(インスタンス)変数やstaticな変数で、それ以外はローカル )  のように代入まで入ってきているようなコードがあった場合は、さら乱雑になるので bool satisfied(ref int value, int value2, int[] values, int index) {   if ( value1 < A ) return true;   if ( !B ) return false;   value1 = values[index];   if ( value1 != C && !D && !E ) return false;   value1 = values[value2];   return value1 = F; }  のようなメソッドに抽出して if ( satisfied(ref value1, value2, values, index) ) … else … のようにしたほうが良いのでしょうか?  ちなみにこれらの条件は(初心者が見る限り多分)これ以上細かく分離できず、再利用される場所がありません。  そのためメソッドにしてしまわず、インデントなどを駆使して if ( value1 < A ||   (     B &&     (       (value1 = values[index]) == C       || D || E     )   )   && (value1 = values[value2]) == F ) else  のようにするだけでも良いのでしょうか?(何だかやりすぎて、逆に見にくくなった気が…)  この辺の事はよくわからないので皆さんのご意見を伺わせてください。

  • C#でビット演算はできますか?

    C#2008で、以下のソースを動かして、OK 2が表示されるのを期待していたのですが、演算子&をintとbool型の演算子に適用できません。 となります。 何か良い方法はありますか? int a = 32 | 16; int b = 8; int c = 16; if (a & b != 0){ MessageBox.Swho("OK 1"); } if (a & c != 0){ MessageBox.Swho("OK 2"); }

  • javaについて質問です

    3つの整数の中央値を求めるメソッドについて質問です。 まずは以下の2つのコードをご覧ください --------------(1)------------------ static int med3(int a,int b,int c){ if(a>=b){ if(b>= c) return b; else if(a<=c) return a; else return c; }else if(a>c) return a; else if(b>c) return c; else return b; } -----------(1)----------- -----------(2)----------- static int med3(int a,int b,int c){ if((b>=a&&c<=a)||(b<=a&&c>=a)) return a; else if((a>b&&c<b)||(a<b&&c>b)) return b; else return c; } -----------(2)----------- 上記の2つのメソッドは参考書の問題に載っているものです。 因みに問題文は、 「中央値を求める手続きは(2)のようにも実現できる。しかしこれは(1)に比べると、実行効率が悪い。その理由を考察せよ」 です。 この問題の解説について質問があります。 解説には、こうあります。 「最初のif文の判定   if ((b >= a && c<= a) || (b <= a && c >= a) に着目します。ここでb >= aおよびb <= aの判定を裏返した判定(実質的に同一の判定)が、続くelse以降で   else if ((a > b && c < b) || (b <= a && c > b) と行われます。つまり、最初のifが成立しなかった場合、2番目のifでも(実質的に)同じ判定を行っているため、効率が悪くなるのです。」 そこで2つ質問があるのですが、まず一つ目から。 「ここでb >= aおよびb <= aの判定を裏返した判定(実質的に同一の判定)が、続くelse以降でelse if ((a > b && c < b) || (b <= a && c > b)と行われます。」の部分の日本語は、一体どういう意味なのでしょうか? b >= a,b <= aの判定を裏返したものはb < a,b > aとなると思うのですが、しかしそれだとその後に続くelse if文の条件、(a > b && c < b) || (b <= a && c > b)と合いません。 2つ目の質問です。 なぜ、ifが成立しなかった場合、何故2番目のifでも同じ判定を行っていると言えるのでしょうか?

    • ベストアンサー
    • Java
  • if文の演算子について

    if文の演算子について int a=0,b=1,c=1,d=1; if(a==1 && b==1 && c==1 ||d==1){ Printf("yes"); }else{ Printf("no"); } if((a==1 && b==1 && c==1 )||d==1){ Printf("yes2"); }else{ Printf("no2"); } } 上記のif文で出力結果が異なります。 if((a==1 && b==1 && c==1 )||d==1)の方はa=1、b=1、c=1の時もしくはd=1の時と 理解できるのですが、 if(a==1 && b==1 && c==1 ||d==1)の方は、どういう条件の時が当てはまるのでしょうか?

  • 仮想基底クラスをもつクラスの代入演算2

    <仮想基底クラスをもつクラスの代入演算>の続きですが、結局、assign のようなものを作って、以下のように書くのが一番いいのでしょうか。。。 ====(一応、自己代入も考慮して書くと^^) #include <algorithm> struct X { int x; X &assign(const X &z, bool top) { if (this != &z) x = z.x; return *this; } X &operator=(const X &z) { return assign(z, true); } }; struct A : virtual X { int a; A &assign(const A &z, bool top) { if (this != &z) { if (top) X::assign(z, false); a = z.a; } return *this; } A &operator=(const A &z) { return assign(z, true); } }; struct B : virtual X { int b; B &assign(const B &z, bool top) { if (this != &z) { if (top) X::assign(z, false); b = z.b; } return *this; } B &operator=(const B &z) { return assign(z, true); } }; struct C : A, B { int c; C &assign(const C &z, bool top) { if (this != &z) { if (top) X::assign(z, false); A::assign(z, false); B::assign(z, false); c = z.c; } return *this; } C &operator=(const C &z) { return assign(z, true); } }; ==== ただ、<仮想基底クラスをもつクラスの代入演算>で、jacta さんが提示してくださった方法も、処理量は増えますが、アロケートする必要があるポインタなどのデータメンバのアロケートやデリートする処理コードをコンストラクタに集中できるので、「コーディング量の減少・改変の際の修正し忘れの可能性を低くできる」というメリットがあると思います。ハンドルクラスやコンテナクラスを実装する際は、swap() 機能が必要となると考えられるので、jacta さんのコピーコンストラクタでコピー代入を実装する方法の方がいいのかとも思います。 みなさん、どう思われますか? また、そのほかに、効果的なテクニックがあれば、ぜひ、ご教示ください。

  • C言語における複素数の四則演算について

    複素数の四則演算(a+biとc+diの四則演算)について、for文を用いて表示するプログラムについて、???の部分に何を入れたらよいかわからず、うまく実行することができません。和・差・積・商の計算種別を入れるみたいなのですが、何を入れたらいいのかわかりません。 #include <stdio.h> void fukuso(double a,double b,double c,double d,double *e,double *f,int keisan); int main(void) { double a=4, b=8, c=4, d=3, e, f; int i; for(i=1;i<5;i++){ fukuso(a,b,c,d,&e,&f,???); if(i==1) printf("和演算\n"); else if(i==2) printf("差演算\n"); else if(i==3) printf("積演算\n"); else printf("商演算\n"); printf("e=%f f=%f i\n",e,f); } return (0); } void fukuso(double a1,double b1,double a2,double b2,double *a3,double *b3,int keisan) { if(keisan==1){ *e=a+c; *f=a+c; } else if(keisan==2){ *e=a-c; *f=b-d; } else if(keisan==3){ *e=a*c-b*d; *f=a*d+c*b; } else{ *e=(a*c+b*d)/(c*c+d*d); *f=(-a*d+c*b)/(c*c+d*d); } }

  • 条件の配列

    表題の件に付いて質問させていただきます。 複数の条件分岐を簡便に記述する方法を探しております。 簡単な例でいいますと、 int main(){  int value=3;  if(value==0)std::cout <<"value="<<0 <<std::endl;  if(value==1)std::cout <<"value="<<1 <<std::endl;  if(value==2)std::cout <<"value="<<2 <<std::endl;  if(value==3)std::cout <<"value="<<3 <<std::endl; } 上記プログラムの複数の条件分岐をfor文をもちいてかきかえる場合、conditionクラスを作成して class condtion{ private:  int *a;  int b; public  void SetPointer(int* value){a=value}  void SetVal(int val){b=val}  bool isTrue(){   if(*a==b){return true;}   else{ return faulse;}  } } int main(){  int value=3;  condition c[4]; //クラス  for(int i=0;i<4;i++){   c[i]->SetPointer(&value);   c[i]->SetVal(i);  }  for(int i=0; i<4; i++){   if(c[i].isTrue())std::cout<<"i="<<i<<std::endl;  } } と実装できそうな気がするのですが、(上記プログラムは動作確認しておりません。) 変数が増えたり、条件が複雑になると少々繁雑になってしまいそうな気がしております。 もっと簡便に条件分岐を配列として処理する方法は存在しますか? 関数ポインタなどがつかえるのでしょうか? アドバイスよろしくお願いいたします。

  • 比較演算子?それとも条件演算子?それとも?

    JavaScriptで、ある条件の式の記述がわからず困っています。 既存のJSを改修しようと思っていますが、知識が足らずに行き詰まりました。 内容 a,b,c,dと4つの箱があり、それぞれ最大3点ずつ得点が入れることができ,0~12点までの得点内容によって結果を5つ表示させたい。 条件 ・トータルポイントが0~1点の時、結果0を表示。 ・トータルポイントが2~12点の時、  aが一番得点が多い時、結果1を表示。  bが一番得点が多い時、結果2を表示。  cが一番得点が多い時、結果3を表示。  dが一番得点が多い時、結果4を表示。 ・得点が同点だった場合、a>b>c>dとなり、結果1を表示。 なんとか自力で下記のような記述をしましたが、結果表示が思ったようになりません。 また、初期変数の記述は省いています。 if(totalPoint <= 1){ resultNum = 0; } else if(totalPoint >= 2){ if(a >= b >= c >= d >= 1){ resultNum = 1; } else if(b >= c >= d >= 1){ resultNum = 2; } else if(c >= d >= 1){ resultNum = 3; } else if(d >= 1){ resultNum = 4; } 演算子も含め、どのような記述であればスマートでしょうか? ご教授いただけますと幸いです。 よろしくお願いいたします。

  • 条件演算子 ? :

    条件演算子 ”?:”をつかってif分と同じようなことができると知りました。 c = (a>b) ? a : 0 ; というようにスルのですが、ふと、条件に満たない場合はそのまま、という場合にはどう記述したらいいのかわかりません。ためしに c = (a>b) ? a : c ; としてみました。これで正しく動作したのですが、 //(a<=b)のときは c = c ; ということになるんですよね。これってなんとなく”無駄”な感じがします。 if文でいうと、"else"を記述しない場合の書き方で、スマートなものはないでしょうか?

    • ベストアンサー
    • Java
  • コンストラクタ内で別のコンストラクタは呼べますか?

    こんにちは。 class CFoo {     CFoo( int a ){}            // 1     CFoo( float b ){}           // 2     CFoo( bool c ){}           // 3     CFoo( int a, float b, bool c )    // 4     {     } } ; 上記のようなクラスで 4 番目のコンストラクタが呼ばれた場合に、 a, b, c のパラメータを使って、1、2、3 を呼ぶようなことは可能でしょうか ? もしご存じの方がいらっしゃいましたら教えて頂けないでしょうか。

専門家に質問してみよう