if ステートメントの条件の最適化
-
09-06-2019 - |
質問
2 つの条件 (OR 演算子で区切られている) を含む if ステートメントがあり、条件の 1 つは状況の +70% をカバーし、処理/実行にかかる時間が 2 番目の条件よりもはるかに短いため、速度の観点から、最初の条件が false と評価された場合に処理される 2 番目の条件。
最初の条件 (より速い方) が最初に if ステートメントに表示されるように条件を順序付けした場合、この条件が満たされて true と評価された場合、2 番目の条件は処理されますか?
if ( (condition1) | (condition2) ){
// do this
}
それとも、最初の条件が false と評価された場合に 2 番目の条件のみをチェックするには、2 つの if ステートメントをネストする必要がありますか?
if (condition1){
// do this
}else if (condition2){
// do this
}
私は PHP で作業していますが、これは言語に依存しない可能性があると思います。
解決
C、C++、C#、Java、およびその他の .NET 言語の場合、ブール式は最適化され、十分なことが判明するとすぐに他には何も評価されなくなります。
難読化されたコードを実行するための古い手法は、これを使用して次のような if ステートメントを作成することでした。
a || b();
「a」が true の場合、「b()」は評価されないため、次のように書き換えることができます。
if(!a)
b();
そして同様に:
a && b();
になるだろう
if(a)
b();
ご注意ください これは||に対してのみ有効であることおよび&&オペレーター。2つの演算子|および&&はビットごとに、およびそれぞれ、したがって、「最適化」されていません。
編集:他の人が述べたように、短絡ロジックを使用してコードを最適化しようとすると、十分な時間が費やされることはほとんどありません。
読みやすく理解しやすいため、まず明確にする必要があります。また、あまりにも賢くしようとしすぎると、用語の単純な並べ替えが、明確な理由もなく大きく異なる動作につながる可能性があります。
次に、最適化を行いますが、それはタイミングとプロファイリングを行った後でのみです。プロファイリングを行わずに時期尚早な最適化を行う開発者が多すぎます。ほとんどの場合、まったく役に立たないのです。
他のヒント
ほぼすべての言語で短絡評価が行われます。つまり、2 番目の条件は、絶対に必要な場合にのみ評価されます。これを機能させるために、ほとんどの言語では単一パイプ || ではなく二重パイプ || を使用します。
C、C++、および Java では、ステートメントは次のようになります。
if (condition1 | condition2) {
...
}
は両方の条件を毎回評価し、式全体が true の場合にのみ true になります。
声明:
if (condition1 || condition2) {
...
}
評価します condition2
場合のみ condition1
は誤りです。条件 2 が関数または副作用のある別の式である場合、その違いは顕著です。
ただし、両者の間に違いはありません。 ||
ケースと if
/else
場合。
最近、n 次の最適化という、この種の質問をたくさん目にしました。
特定の状況ではそれが理にかなっていると思います。
- 演算条件 2 は定数時間演算ではありません
- あなたは厳密に教育目的で質問しています。3us を節約するためではなく、言語がどのように機能するかを知りたいのです。
他の場合には、条件を繰り返したりチェックしたりする「最速の」方法を心配するのは愚かです。記録可能な (ただし重要ではない) 違いを確認するために何百万もの試行を必要とするテストを作成するのではなく、明確さに重点を置きます。
他の誰か (あなたかもしれません!) が 1 か月または 1 年後にこのコードを入手したとき、最も重要になるのは明確さです。
この場合、最初の例はより短く、明確であり、同じことを繰り返す必要はありません。
によると この記事 PHP は短絡評価を行います。つまり、最初の条件が満たされた場合、2 番目の条件は評価されません。テストも非常に簡単です (記事より):
<?php
/* ch06ex07 – shows no output because of short circuit evaluation */
if (true || $intVal = 5) // short circuits after true
{
echo $intVal; // will be empty because the assignment never took place
}
?>
短絡は最適化のためのものではありません。その主な目的は、読みやすいテストが得られるにもかかわらず、機能しないコードの呼び出しを回避することです。例:
if (i < array.size() && array[i]==foo) ...
i が範囲外の場合、array[i] はアクセス違反を起こし、プログラムをクラッシュさせる可能性があることに注意してください。このように、このプログラムは確かに評価の短絡に依存しています。
これが、最適化の問題よりもこの方法で式を記述することがはるかに多い理由であると私は考えています。
最適化の目的で短絡を使用するのは過剰であることがよくありますが、短絡を使用する他のやむを得ない理由があることは確かです。そのような例の 1 つ (C++ の場合) は次のとおりです。
if( pObj != NULL && *pObj == "username" ) {
// Do something...
}
ここでは、短絡を利用して次のことを保証します。 pObj
逆参照する前に割り当てられています。これはネストするよりもはるかに簡潔です if
発言。
これは言語に依存しないタグが付けられているので、私も参加させていただきます。少なくとも Perl の場合は、最初のオプションで十分です。私は PHP には詳しくありません。左から右に評価され、条件が満たされるとすぐに削除されます。
適切な最適化が行われているほとんどの言語では、前者は問題なく動作します。
の |
PHP のビット演算子です。そんな意味じゃない $a OR $b
, 、 その通り。二重パイプを使用すると良いでしょう。そしてはい、前述したように、PHP はショートサーキット評価を行います。同様に、最初の条件が &&
句が false と評価されると、PHP は句の残りの部分も評価しません。
VB.net には「OrElse」と「AndAlso」という 2 つの素晴らしい表現があります。
OrElse は、初めて True 評価に達したときに自身をショートさせ、必要なコードを実行します。
If FirstName = "Luke" OrElse FirstName = "Darth" Then
Console.Writeline "Greetings Exalted One!"
End If
AndAlso は、初めて False 評価が行われたときに自身をショートさせ、ブロック内のコードを評価しません。
If FirstName = "Luke" AndAlso LastName = "Skywalker" Then
Console.Writeline "You are the one and only."
End If
どちらも役立つと思います。