初歩的な質問ですみません。or 条件で処理をする時複数の書き方が3パターン存在すると思いますが、どのような書き方が早い処理をできるのでしょうか?
2番目と3番目は結構無理やりですが、単純にこういう書き方をした時の速度の違いが知りたいので書きました
if(joken1 || joken2 ||joken3){ //処理1 }
と
if(jogen1){ //処理1 }else if(jogen2){ //処理1 }else if(joken3){ //処理1 }
と
if(joken1){ //処理1 } if(joken2){ //処理1 } if(joken3){ //処理1 }
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答7件
0
処理速度の前に、これらの3つですが、処理として意味合いが異なってきます。
c++
1if (joken1 || joken12 || joken3) { 2 //ここの処理はjoken1,joken2,joken3の少なくとも1つがtrueなら処理される 3} 4 5if (joken1) { 6 //joken1がtrueの時処理される 7} else if (joken2) { 8 //joken1がfalseでjoken2がtrueの時に処理される 9} else if (joken3) { 10 //joken1とjoken2がfalseでjoken3がtrueの時に処理される 11} 12 13if (joken1) { 14 //joken1がtrueの時処理される 15} 16if (joken2) { 17 //joken1と関係なくjoken2がtrueの時処理される 18} 19if (joken3) { 20 //joken1,joken2と関係なくjoken3がtrueの時処理される 21} 22
となりますので、
- 処理がどういうものか?
- その条件は何なのか?
- 各条件に依存関係はあるのか?
など考慮した上でどういうロジックにするのかを考える必要があります。
つまり、もし、「処理1」全て同じなら、1番目と2番めは「処理1」は1回しか処理されないが、3番めはjoken1,2,3が全てtrueの場合3回「処理1」を実行してしまうということです。(処理速度よりロジックを考えるべき)
質問の処理速度について一応答えておくと、joken1,joken2,joken3が全てtrueの場合、3番めの処理は「処理」が3回実行されることになるので一番時間がかかることになるでしょう。
2番めは、joken1,joken2,joken3の状態によって変わります。joken1がtrueならそのチェックだけで処理が実行されますが、joken1,joken2がfalseならjoken3のチェックまで行われるのでその分時間は掛かります。(と言っても一瞬ですけどね)
1番めは、joken1,joken2,joken3の状態によって処理速度は「たぶん」変わりません。(「たぶん」というのは、コンパイラーが吐き出すコードに依存します。条件の評価が仮に先頭からとして全て||
で繋いでいるので1つでもtrueがあったら処理を実行するようなコードを吐き出すコンパイラなら、joken1,2,3の状態に依存することになります。)
ただ、joken1,joken2,joken3がboolなどの変数なら、条件のチェックは一瞬で終わるので、「処理」の内容に速度は依存することになるでしょうね。(この処理を数万回繰り返すのなら別ですが)
投稿2017/07/25 08:53
総合スコア3579
0
回答としては Chironian さんに一票ですが、コンパイラの最適化の話があるので、少し実験してみました。1番目と2番目の比較について、
C
1#include <stdio.h> 2extern int i; 3extern init(int); 4extern process1(); 5 6 7void test1() { 8 if (i < 3 || i ==5 || i == 7) { 9 process1(); 10 } 11} 12 13void test2() { 14 if (i < 3) { 15 process1(); 16 } else if (i == 5) { 17 process1(); 18 } else if (i == 7) { 19 process1(); 20 } 21} 22 23int main(){ 24 init(3); 25 test2(); 26 test1(); 27} 28
これを cc -c a.c -O2 でコンパイルしてディスアセンブルすると、
asm
10000000000000000 <test1>: 2 0: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 6 <test1+0x6> 3 6: 89 c2 mov %eax,%edx 4 8: 83 e2 fd and $0xfffffffd,%edx 5 b: 83 fa 05 cmp $0x5,%edx 6 e: 74 10 je 20 <test1+0x20> 7 10: 83 f8 02 cmp $0x2,%eax 8 13: 7e 0b jle 20 <test1+0x20> 9 15: f3 c3 repz retq 10 17: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 11 1e: 00 00 12 20: 31 c0 xor %eax,%eax 13 22: e9 00 00 00 00 jmpq 27 <test1+0x27> 14 27: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 15 2e: 00 00 16 170000000000000030 <test2>: 18 30: 8b 05 00 00 00 00 mov 0x0(%rip),%eax # 36 <test2+0x6> 19 36: 83 f8 02 cmp $0x2,%eax 20 39: 7e 0d jle 48 <test2+0x18> 21 3b: 83 e0 fd and $0xfffffffd,%eax 22 3e: 83 f8 05 cmp $0x5,%eax 23 41: 74 05 je 48 <test2+0x18> 24 43: f3 c3 repz retq 25 45: 0f 1f 00 nopl (%rax) 26 48: 31 c0 xor %eax,%eax 27 4a: e9 00 00 00 00 jmpq 4f <test2+0x1f> 28
ほぼ、同じコードが出ていることがわかります。 catsforepaw さんのおっしゃるとおり、大胆に改変されていますが、この程度の単純な条件式であれば、2番めのパターンでも1番目と同様に最適化してしまいますね。test2() で process1() の呼び出しは3個書いても1個しかでてませんし、比較条件の順番が入れ替わってますが、やってる内容はほぼ同じです。
しかし、 == 7 を比較するのに2ビット目をマスクして == 5 の比較を共用するとは・・・
私の結論としては、2番めでも速度的には1番目と変わりませんが、保守性の問題で1番目で書くべきだと思います。
テスト環境は Centos 7 x86_64 で、コンパイラのバージョンは
cc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11)
です。
投稿2017/08/01 02:57
総合スコア3401
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ほかの方もおっしゃっているとおり、1番目と2番目は同じ結果になりますが、3番目は明らかに無駄な処理が発生する(場合によっては処理結果が異なる)ので比較対象からは外すべきでしょう。
ということで、1と2に絞って速度に違いがあるかどうかですが、結論から言うと違いが出る可能性があるということになります。さらに言えば、1番目の方が速くなる可能性が高いです。
その理由はコンパイラーの最適化です。最適化においては、関連する処理(特に計算処理)が近い場所にあると最適化が効きやすいという性質があるためです。
1番目のコードはjoken1~3が一続きの式になっていて、最終的に処理1にたどり着きます。一方、2番目の方は、joken1~3が異なるif文に分かれていて、さらに、処理1も同様に分かれています。処理内容にもよりますが、1番目の方が最適化が効きやすいのは一目瞭然です。
今時のコンパイラーはとても賢いので、最適化を有効にすると計算式を「解析」して結果を損なわない範囲で「(大胆に)改変」します。
例えば、
if(x == 1 || x == 2 || x == 3) { 処理 }
このようなコードは最適化によって
// ※擬似コード if((unsigned)x - 1 <= 2) { 処理 }
のように「改変」されたりします。
投稿2017/07/25 12:10
総合スコア5944
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
処理速度云々の前に
2番目のコード
if(jogen1){ //処理1 }else if(jogen2){ //処理1 }else if(joken3){ //処理1 }
3箇所に全く同じ処理「処理1」を記述するのはどうかと思うけど・・・
普通に考えると、上記のようなコーディングをされると、それぞれ別の処理「処理1」「処理2」「処理3」が記述されるはずだけど、ぱっと見同じっぽい。バグっぽいな・・・。
と感じてしまうと思う。
因みに、3番目のコードは
if(joken1){ //処理1 return; } if(joken2){ //処理1 return; } if(joken3){ //処理1 return; }
とすれば、2番目と一緒かと。
いずれにせよ、「普通」ではないと思う。
投稿2017/08/11 13:07
総合スコア18
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/08/01 00:56
2017/08/01 07:55