7

最小限の手順で 3 つの条件を評価する最も簡単な方法について、誰か助けてくれませんか? 3 つの条件があり、2 つのいずれかが true になると、式全体がtrueelse になりますfalse

私は2つの方法を試しました:

if ((condition1 && condition2) || 
    (condition1 && condition3) || 
    (condition2 && condition3))

別の方法は、変数iを導入して

i = 0;
if (condition1) i++;
if (condition2) i++;
if (condition3) i++;
if (i >= 2)
    //do something

上記の2つよりも効果的な方法が他にあるといいのですが。

メモリに制約のある環境 (8 KB のフラッシュ メモリを搭載した Atmeta8) で作業しており、C で動作するソリューションが必要です。

4

8 に答える 8

9

これは次のように削減できます。

if((condition1 && (condition2 || condition3)) || (condition2 && condition3))
    //do something

各条件の可能性に応じて、順序を最適化して短絡を高速化できる場合があります (ただし、これはおそらく時期尚早の最適化になります...)。

于 2013-06-20T14:18:16.647 に答える
4

「より良い」解決策を提供することは常に困難です (コード行、読みやすさ、実行速度、マシンコード命令のバイト数など、どの点でより良いのでしょうか?)。この場合、それに集中できます。

提案するその変数を導入し、それを使用して条件を単純なより小さい条件に減らし、答えがわかったら使用できます。より小さい条件は、ほとんどのアーキテクチャで 2 つのマシン コード命令に自明に変換されます (たとえば、Intel IA-32ではCMP(compare) の後にJL(より小さい場合はジャンプ) または(小さくない場合はジャンプ) が続きます)。少し運が良ければ、コンパイラーは最初の 2 つのステートメントで常にtrue になるJNLことに気付き (または自分で行うこともできますが、どこでも同じパターンを持つことで得られる明快さを好みます)、それを最適化します。trues < 2if()

int trues = 0;
if (trues < 2 && condition1) trues++;
if (trues < 2 && condition2) trues++;
if (trues < 2 && condition3) trues++;
// ...
if (trues >= 2)
{
    // do something
}

これは、答えが分かれconditionNば、ほとんどの言語のブール短絡動作のために、複雑な可能性のある評価を単純なより小さい比較に減らします。

言語でブール条件を整数にキャストできる場合は、それを利用してソースコードの行数を減らすことができます。ただし、引き続き各条件を評価します。

if( (int)(condition1)
  + (int)(condition2)
  + (int)(condition3)
  >= 2)
{
    // do something
}

これは、ブール値の FALSE 値を整数にキャストすると 0 になり、TRUE をキャストすると 1 になるという前提に基づいて機能します。同じ効果のために条件演算子を使用することもできますが、追加の分岐が発生する可能性があることに注意してください。

if( ((condition1) ? 1 : 0)
  + ((condition2) ? 1 : 0)
  + ((condition3) ? 1 : 0)
  >= 2)
{
    // do something
}

コンパイラのオプティマイザーの能力によっては、2 つの条件が true と評価されると、条件全体が常に true と評価され、それに基づいて最適化されると判断できる場合があります。

  • コードを実際にプロファイリングして、これが原因であると判断した場合を除き、最適化が時期尚早である可能性が高いことに注意してください。見ているコードの特定の部分が実際のパフォーマンスのボトルネックであるという決定的な証拠を示すことができない限り、コードは常に最初に人間のプログラマーが読み取り可能であり、次にコンピューターが高速に実行できるように努めてください。そのプロファイラーがどのように機能するかを学び、有効に活用してください。ほとんどの場合、プログラマーの時間は CPU 時間よりもはるかにコストがかかり、巧妙な手法はメンテナンス プログラマーが解析するのに時間がかかることに注意してください。
  • また、コンパイラは非常に賢いソフトウェアです。書かれたコードの意図を実際に検出し、それらの操作を高速化するための特定の構造を使用できる場合もありますが、それは、何をしようとしているのかを判断できることに依存しています。これの完璧な例は、中間変数を使用して 2 つの変数を交換することです。これは、IA-32XCHGでは中間変数を削除することで実行できますが、コンパイラーは、実際にそれを行っていることを判断できなければならず、何かを与える可能性のある巧妙なものではありません。場合によっては別結果
  • 明示的に書かれていない使い捨てソフトウェアの大部分は、そのライフタイムの大部分を保守モードで過ごすため (そして、書かれた使い捨てソフトウェアの多くは有効であり、意図した賞味期限をはるかに過ぎています)、保守性を最適化することは理にかなっています。それが他の点で容認できないほどの代償を伴う場合を除きます。もちろん、これらの条件をタイトなループ内で 1 兆回も評価している場合、ターゲットを絞った最適化は非常に理にかなっている可能性があります。しかし、プロファイラーは、コードのどの部分をパフォーマンスの観点からより綿密に精査する必要があるかを正確に教えてくれるので、コードが不必要に複雑になるのを避けることができます。

そして、上記の注意点によると、私は最近コードに取り組んでおり、一見したところ、詳細の最適化が時期尚早であるとほぼ確実に考えられるような変更を加えています。高パフォーマンスが必要で、プロファイラーを使用してコードのどの部分がボトルネックであるかを判断する場合、最適化は時期尚早ではありません。(ただし、正確な状況によっては、依然として不適切な場合があります。)

于 2013-06-20T14:20:22.707 に答える
3

あなたの言語にもよりますが、私は次のようなことに頼るかもしれません:

$cond = array(true, true, false);

if (count(array_filter($cond)) >= 2)

また

if (array_reduce($cond, function ($i, $k) { return $i + (int)$k; }) >= 2)
于 2013-06-20T14:14:48.367 に答える
1

これには絶対的な答えはありません。これは、基盤となるアーキテクチャに大きく依存します。たとえば、VHDL または Verilog でハードウェア回路をプログラムする場合、確かに最初の方が最速の結果が得られます。あなたのターゲットはある種のCPUだと思いますが、ここでもターゲットCPU、サポートする命令、およびそれらにかかる時間に大きく依存します。また、ターゲット言語を指定しません (たとえば、最初のアプローチが短絡して速度に大きな影響を与える可能性があります)。

他に何も知らない場合は、2 番目の解決策をお勧めします。これは、意図 (少なくとも 2 つの条件が true である必要があります) がコードによりよく反映されるという理由だけです。

2 つのソリューションの速度の差はそれほど大きくありません。これが単なるロジックであり、何度も実行される最も内側のループの一部ではない場合、最適化が時期尚早であると推測し、別の場所で最適化を試みることさえあります。

于 2013-06-20T14:21:37.780 に答える