1

注: 私はこれが受け入れられるコードではないことを認識しています。同じ結果を達成するための他の方法についてのアドバイスではなく、インタプリタが何をしているかを理解しようとしています!

それ以来、|,|| を使用することはできませんし、使用するべきではないことを理解するのに十分な量を読みました。または、switch ケースを定義する際の XOR です。つまり、「そんなことはしないでください」という趣旨のコメントはしないでください。私は、インタープリターがそのようなステートメントで何をしているのかを理解し、動作の奇妙さを理解しようとしているだけです。PHP 5.3.1 を使用しています。

これは私が実際にやろうとしていたことであり、現在使用しています。コードを推奨しないでください:

for ($i=0; $i<count($this->header); $i++) {
            switch($i) {
                case 0:
                    $this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : -5;   //angle from goal
                    break;
                case 1:
                    $this->header[$i] = $this->header[$i] ? $this->header[$i] : -5;         //miss penalty
                    break;
                case 2:
                    $this->header[$i] = $this->header[$i] ? $this->header[$i] : -10;         //miss penalty
                    break;
                case 3:
                    $this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : -10;  //error penalty
                    break;
            }
        }

しかし、私ができるかどうか興味がありました:

for ($i=0; $i<count($this->header); $i++) {
            switch($i) {
                case 0 || 1:
                    $this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : 15;   //angle from goal
                    break;
                case 2 || 3:
                    $this->header[$i] = $this->header[$i] ? $this->header[$i] : -5;         //miss penalty
                    break;
            }
        }

そして、逆に、これは実行されますが、非常に遅く (数秒程度)、もちろん、(0||1)私が意図したとおりには評価されません (実際、今日はビットごとの演算子と論理演算子の違いに関するレッスンでした)。

しかし、私にとってもっと興味深かったのは、非常にゆっくりと、私が望んでいた結果ではなかったとしても、これを行うことができるという事実でした:

for ($i=0; $i<count($this->header); $i++) {
            switch($i) {
                case 0 XOR 1:
                    $this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : 15;   //angle from goal
                    break;
                case 2:
                    $this->header[$i] = $this->header[$i] ? $this->header[$i] : -5;         //miss penalty
                    break;
                case 3:
                    $this->header[$i] = $this->header[$i] ? $this->header[$i] : -5;         //miss penalty
                    break;
            }
        }

しかし、私はこれを行うことができませんでした:

for ($i=0; $i<count($this->header); $i++) {
            switch($i) {
                case 0 XOR 1:
                    $this->header[ $i ] = $this->header[ $i ] ? $this->header[ $i ] : 15;   //angle from goal
                    break;
                case 2 XOR 3:
                    $this->header[$i] = $this->header[$i] ? $this->header[$i] : -5;         //miss penalty
                    break;
            }
        }

これは、PHP が評価さえしない、これらの恐ろしい、恐ろしいアイデアの 1 つだけでした。

私の質問は、なぜこれらのステートメントを評価するのにそんなに時間がかかるのですか? また、最後の例が実行されないのはなぜですか? PHP は 0 XOR 1 を解釈して と を比較しtrueているとfalse思いましたが、それらを置き換えて評価することはできませんでした。ここで何が起こっているか知っている人はいますか?ありがとう!


アップデート:

コメントは a を要求しましたvar_dump($this->header)(明らかでない場合に備えて、同じコードのスパム行を避けるために、最初の switch ステートメントを 7 ケースから 4 ケースに切り捨てましたが、var_dump()が要求された場合に備えて、すべてを投稿することにしました。予想できなかったことが明らかになりました!)array_values()また、はい、以下の2番目の回答で、設定する前に呼び出すのを忘れたため、連想配列を使用していたことがわかりました。このエラーを作成すると、ステートメント$this->headerの期間が説明されますが、最初の回答と2番目switch一緒に答えることは、ロジックの優れたウォークスルーです。

array(12) {
  ["theZone"]=>
  NULL
  ["leftMiss"]=>
  NULL
  ["rightMiss"]=>
  NULL
  ["leftError"]=>
  NULL
  ["rightError"]=>
  NULL
  ["leftHit"]=>
  NULL
  ["rightHit"]=>
  NULL
  ["accuracy"]=>
  string(5) "false"
  ["rt"]=>
  string(4) "true"
  ["disease"]=>
  string(3) "yes"
  ["bars"]=>
  string(3) "yes"
  ["endMessage"]=>
  NULL
}
4

2 に答える 2

1

ははは、あなたがそこで何をしたか、それはかなり面白いです。

パフォーマンスの問題を引き起こすのはスイッチではありません。おそらく、スイッチと組み合わせた for ループです。

与えられた2番目の例でそれを説明しようとします。

ただし、推測する必要があるため、 $this->header 配列が次のようになっていると想定する必要があります (これがパフォーマンス リークの唯一の理由です)。

$this->header = array(
  999 => 10,   // the value is irrelevant, only the key (2) matters
  998 => 15
);

では、インタープリター デバッガーを再生してみましょう。

set $i to 0
is $i<count($this->header)? yes, because header size is 2
is ($i == (0 || 1))? no, because (0 == (0 || 1)) equals (0 == true) equals (false == true) can never be true
is ($i == (2 || 3))? no, because (0 == (2 || 3)) equals (0 == true) equals (false == true) will never comply
next loop, increment $i (set $i to 1)
is ($i<count($this->header)? yes, because header size is 2
is ($i == (0 || 1))? yes, because (1 == (0 || 1)) equals (1 == true) equals (true == true)
go into case statement
set $this->header[1] to -5  (remember the index 1 does not exist so far in your array)
next loop, increment $i (set $i to 2)
is $i<count($this->header)? yes, because header size is 3 (remember? you just added a new index which incremented your header size)
is ($i == (0 || 1))? yes, because (2 == (0 || 1)) equals (2 == true equals (true == true)
go into case statement
set $this->header[2] to -5 (again index 2 did not exist so far)
next loop, increment $i (set $i to 3)
is $i<count($this->header)? yes, because header size is 4 (again, you just added a new index)

これは、ヘッダー サイズが $i に等しくなるまで続きます。上記の例では、これは 998 回の繰り返しの後に発生します。これは、新しいインデックスが作成されないのが初めてであり (既存のもの - 998 - が単に使用される)、count($this->header )変わらない。

最初の例では、これは起こりません。case ステートメントはブール値ではなく整数値を比較しようとするため、ヘッダー サイズは 4 回目の反復後に変化しなくなります。インデックス 5 に到達するとすぐに、値 1、2、3、および 4 との比較を試みますが、1 つの値と一致しないため、新しいインデックスは作成されません。

パフォーマンスの問題を修正するには、配列内のすべてのキーが存在することを確認し、for ループを次のように変更する必要があります。

$size = count($this->header);
for($i=0; $i<$size); $i++) {...}

もちろん、これで論理的な問題が解決されるわけではありません。しかし、あなたは何が起こっているのか尋ねたので、これは良い説明になるはずです.

ループの前後に $this->header 配列を var_dump()-ing すると、私が正しいことが証明されるはずです:)

===

この回答を削除して取り消して申し訳ありません。説明どおりに実際に動作することを確認したかっただけです。ヘッダー配列の var_dump を提供していただけると助かります。

于 2013-07-19T20:43:02.143 に答える