1


0

2つの範囲をループするより良い方法は何ですか?それらを一緒に乗算して1回ループするか、各範囲を個別にループしますか?

範囲をループする方法を決定できません。 こちらです:

for (int i = 0; i < max_i; i++) {
    for (int j = 0; j < max_j; j++) {
        // first way - two loops
    }
}

またはこのように:

for (int k = 0; k < max_i*max_j; k++) {
    // second way - one loop
}

ありがとう、Boda Cydo。

10 Answer


7


それは、インデックスをどうするかによって異なります。 2つの値を別々に使用している場合(たとえば、2つのループ内の値のすべての順列を反復処理している場合)、2つのループのソリューションはより明確です。 個別の値を気にせず、代わりにその製品だけを使用する場合は、1ループ戦略の方が適しています。

どちらにしても、あなたの意図をより明確に表現する戦略を選択してください。 コードを維持するシンプルさの重要性と比較すると、パフォーマンスへの影響はささいなものです。


4


最初のループは、少なくとも2つの理由で優れています。

  1. ループのネストされた性質を読者に明確にする (必要なものに応じて)

  2. 2番目の選択肢でmax_i * max_jがオーバーフローするとどうなりますか?

また、ループインデックス変数を 'int’または 'size_t’にする必要があるかどうかを調べてください。 size_tは常に正であることが保証されています


3


max_i`または/および max_j`が十分に大きい場合、2番目のバリアントを使用できません。 int`は符号付き型であることに注意してください。 `sizeof(int)`が4バイトに等しい場合、 `max_i = 32768`と max_j = 65536`の場合、ループは0回実行されます。

特別な要件がない場合は、読みやすいため、最初のバリアントを選択します。


2


ループ内で何をするかによって異なります。 インデックスiとjが必要ですか? それから私は最初の解決策を好むでしょう。


2


最初の方法を選択した場合、 i`と j`の両方の値を持っているため、すべてが良好です。 2番目の方法では、 i`と j`の値を手動で取得する必要があります。

for (int k = 0; k < max_i*max_j; k++) {
    i = k / max_j;
    j = k % max_j;
    ....
}

だから、あなたの場合、最初の方法は間違いなく優れています。


2


もちろん、選択できる場合は、ループ中にiとjの正確な値は必要ありません。

したがって、2番目のオプションの方が優れていて、読みやすくなっています(インデントが少なくなります)。 少しの最適化を行うことができます(各ループ反復で乗算を行わないように):

int iKMax = max_i*max_j;
for (int k = 0; k < iKMax ; ++k)
{
    // second way - one loop
}

また、ループでプレフィックス演算子を常に使用すると( k)、オブジェクトが繰り返されるものが何であれ、このオブジェクトのコピーが1つ節約されます。 (cf. C コーディング標準:101ルール、ガイドライン、およびベストプラクティスby Herb SutterおよびAndrei Alexandrescu)


0


まあそれは依存します。 *別のインデックス*が必要な場合は、最初のインデックスを使用できます。 *シングルインデックス*のみが必要な場合は、2番目のインデックスです。

両方のループの複雑さは同じです。


0


2D配列を使用する場合、最初の配列ははるかに読みやすいものではありません。 以前は、2D配列を1Dでエミュレートするのが一般的でしたが、この場合も最初の配列は読みやすいです。


0


疑わしい場合は、コンパイラがあなたよりも最適化されると想定してください。

これはAndroid 1.0のようなものには絶対に当てはまりませんが、ほとんどのC / C ++コンパイラーはかなり優れています。 優れたコンパイラーは、単純な2D配列アクセスを最適化できるはずです(例: 配列のすべての値を合計して1つのループにします。


0


これがあなたがそれをすることができるもう一つの方法です:

for(int i = 0、j = 0; i <max_i、j