昨夜は試作中のゲームプログラムに思いつきで手を加えて速度計測をしましたので、重大なバグが2箇所ありました。LONGLONG型を"%d, %d, %d, %d, %d, %d"で出力していたり…。
&&に関しては、左から右へ順に評価して行き、偽になった時点で残りの評価を無視して全体の評価が偽になるので極端な話、0を返しやすい関数ほど右へ置くのがベストみたいですね。
加算の条件式に関しては、int型の上限値である2147483647にint型の数値(1~2147483647)を加算すると最上位ビットが立って、一旦下限値である-2147483648になり、そこからオーバーフローした分(加算値 - 1)が加算される結果になるとは、実戦してみて驚きました。
コードによって、コンパイラがオーバーフローを警告しない場合・警告するけど続行する場合・エラーになる場合が有り、必ずエラー停止するものだと思っていた自分の認識が甘かったです。
唯一関数返り値が負の場合に使えないと思っていた条件式に、更に落とし穴があるとは思いもよりませんでした。
そして、またまた今日も無駄かも知れないコーディング(珍道中)の始まりです。OS含む他の実行中プログラムやマシン特有の問題等も考慮すると真の速度が計れないのは百も承知ですが、大体の目安を確認しようと思います。
昨日同様、以下の正の数しか返さないint型関数全ての返り値が0である場合に真となる条件式を使った条件判断文を、if文とwhile文で3個ずつ作ります。
この例で自分が利用する関数は0~20程度の値しか返ってこないので、今回もif文2とwhile文2を使用します。
if文1: if (Func1() == 0 && Func2() == 0 && Func3() == 0) {}
if文2: if (Func1() + Func2() + Func3() == 0) {}
if文3: if ((Func1() | Func2() | Func3()) == 0) {}
while文1: while (Func1() == 0 && Func2() == 0 && Func3() == 0) { break; }
while文2: while (Func1() + Func2() + Func3() == 0) { break; }
while文3: while ((Func1() | Func2() | Func3()) == 0) { break; }
今回は、条件式が偽になる場合も含め、返り値の範囲を
Func1() = 0 ~ 9
Func2() = 0 ~ 9
Func3() = 0 ~ 9
として、全ての可能性(10×10×10 = 1000通り)で計測する事にしました。
という訳で、専用にコードを組んで出力してみた所、1000通りの合計処理時間[μs]が、
if文1: 25167
if文2: 24948
if文3: 24809
while文1: 24895
while文2: 24854
while文3: 24801
になりました。とある1回の試行結果です。個々の値はプログラム実行の度にかなりズレる事もありますが、凡そこんな感じです。
全1000通り中、Func1()が0でない場合が900通り(90%)もあるのに、&&比較が特に速いという痕跡は見当たりません。
マシンの計算能力が高過ぎるのか、関数呼出しや条件式評価でのこの程度の負荷では人間様には速度差が分かりませんというのが現実の結果です。
結構下らない事に時間を費やしている今日この頃です。