128

ループを 7 回繰り返す必要がある場合は、次のようにします。

for (int i = 0; i < 7; i++)

また:

for (int i = 0; i <= 6; i++)

次の 2 つの考慮事項があります。

  • パフォーマンス
  • 可読性

パフォーマンスのために、Java または C# を想定しています。「未満」または「以下」が使用されているかどうかは重要ですか? 別の言語についての洞察がある場合は、それを示してください。

読みやすくするために、0 ベースの配列を想定しています。

UPD: 0 から始まる配列についての私の言及は、物事を混乱させた可能性があります。配列要素を繰り返し処理することについて話しているのではありません。単なる一般的なループ。

このマジック ナンバーが何であるかを説明する定数の使用について、以下に良い点があります。もし私が " int NUMBER_OF_THINGS = 7" を持っていたら " i <= NUMBER_OF_THINGS - 1" は奇妙に見えるでしょうね。

4

39 に答える 39

292

最初のものはより慣用的です。特に、反復回数を (0 ベースの意味で) 示します。1 ベースのもの (JDBC、IIRC など) を使用する場合、<= を使用したくなるかもしれません。そう:

for (int i=0; i < count; i++) // For 0-based APIs

for (int i=1; i <= count; i++) // For 1-based APIs

実際のコードでは、パフォーマンスの違いはごくわずかであると予想されます。

于 2008-10-08T13:03:44.750 に答える
72

これらのループは両方とも 7 回反復します。他に本当に正当な理由がない限り、7が含まれている方が読みやすく/明確だと思います。

于 2008-10-08T13:02:32.253 に答える
56

大学で8086アセンブリを行ったときから、次のことを行う方がパフォーマンスが良かったことを覚えています。

for (int i = 6; i > -1; i--)

兆候がない場合はジャンプを意味するJNS操作があったため。これを使用すると、各サイクルの後に比較値を取得するためのメモリルックアップがなく、比較も行われませんでした。最近では、ほとんどのコンパイラがレジスタの使用を最適化するため、メモリの問題はもはや重要ではありませんが、それでも不要な比較が可能です。

ちなみに、ループに7または6を入れると、「マジックナンバー」が導入されます。読みやすくするために、意図を明らかにする名前の定数を使用する必要があります。このような:

const int NUMBER_OF_CARS = 7;
for (int i = 0; i < NUMBER_OF_CARS; i++)

編集:人々はアセンブリのものを取得していないので、より完全な例が明らかに必要です:

(i = 0; i <= 10; i ++)の場合、これを行う必要があります。

    mov esi, 0
loopStartLabel:
                ; Do some stuff
    inc esi
                ; Note cmp command on next line
    cmp esi, 10
    jle exitLoopLabel
    jmp loopStartLabel
exitLoopLabel:

(int i = 10; i> -1; i--)を実行すると、次のように回避できます。

    mov esi, 10
loopStartLabel:
                ; Do some stuff
    dec esi
                ; Note no cmp command on next line
    jns exitLoopLabel
    jmp loopStartLabel
exitLoopLabel:

確認したところ、MicrosoftのC ++コンパイラはこの最適化を実行しませんが、実行すると次のようになります。

for (int i = 10; i >= 0; i--) 

したがって、道徳は、Microsoft C ++†を使用していて、昇順でも降順でも違いがない場合、すばやくループを取得するには、次のように使用する必要があります。

for (int i = 10; i >= 0; i--)

これらのいずれかではなく:

for (int i = 10; i > -1; i--)
for (int i = 0; i <= 10; i++)

しかし、率直に言って、「for(int i = 0; i <= 10; i ++)」の可読性を取得することは、通常、1つのプロセッサコマンドを見逃すよりもはるかに重要です。

†他のコンパイラは異なることをするかもしれません。

于 2008-10-08T13:30:32.823 に答える
27

<= array.length-1 よりも読みやすいため、私は常に < array.length を使用します。

また、< 7 であり、インデックス 0 で始まることがわかっていることを考えると、その数が反復回数であることは直感的にわかるはずです。

于 2008-10-08T13:02:54.250 に答える
18

最適化の観点から見ると、それは問題ではありません。

コード スタイルの観点から見ると、私は < を好みます。理由:

for ( int i = 0; i < array.size(); i++ )

よりもはるかに読みやすいです

for ( int i = 0; i <= array.size() -1; i++ )

また < は、反復回数をすぐに示します。

< に対するもう 1 つの投票は、偶発的なオフ・バイ・ワンのミスを多く防ぐことができるということです。

于 2008-10-08T13:04:32.017 に答える
10

@Chris、.NETでコストがかかる.Lengthに関するあなたの声明は実際には真実ではなく、単純な型の場合は正反対です。

int len = somearray.Length;
for(i = 0; i < len; i++)
{
  somearray[i].something();
}

実際にはより遅いです

for(i = 0; i < somearray.Length; i++)
{
  somearray[i].something();
}

後者は、ランタイムによって最適化されるケースです。ランタイムは i が配列への有効なインデックスであることを保証できるため、境界チェックは行われません。前者では、ランタイムは、ループの前に i が変更されていないことを保証できず、すべてのインデックス ルックアップに対して配列の境界チェックを強制します。

于 2008-10-08T16:03:29.130 に答える
6

パフォーマンスに関しては、効果的な違いはありません。したがって、解決している問題のコンテキストで理解しやすい方を使用します。

于 2008-10-08T13:02:16.797 に答える
5

私が好む:

for (int i = 0; i < 7; i++)

これは、「ループを 7 回反復する」という意味に簡単に変換できると思います。

パフォーマンスへの影響についてはわかりません-違いがあればコンパイルされてしまうと思います。

于 2008-10-08T13:03:11.083 に答える
5

C++ では、!=すべての STL コンテナーで使用できる を使用することを好みます。すべての STL コンテナ イテレータが比較に劣るわけではありません。

于 2008-10-08T14:56:59.497 に答える
4

「< 7」バージョンを使用することをお勧めします。これは、大多数の人が読むものだからです。そのため、人々があなたのコードをざっと読んでいると、間違って解釈する可能性があります。

「<」が「<=」よりも速いかどうかは気にしません。読みやすさだけを考えてください。

速度を上げたい場合は、次の点を考慮してください。

for (int i = 0; i < this->GetCount(); i++)
{
  // Do something
}

パフォーマンスを向上させるために、次のように少し再配置できます。

const int count = this->GetCount();
for (int i = 0; i < count; ++i)
{
  // Do something
}

ループからの GetCount() の削除 (すべてのループで照会されるため) と、"i++" から "++i" への変更に注意してください。

于 2008-10-08T13:09:20.323 に答える
4

Java 1.5では、次のことができます

for (int i: myArray) {
    ...
}

したがって、配列の場合は心配する必要はありません。

于 2008-10-08T13:02:52.613 に答える
4

性能差はないと思います。ただし、2 番目の形式の方が読みやすいのは間違いありません。最後の反復回数を見つけるために頭の中で 1 を引く必要はありません。

編集:他の人が同意しないのを見ます。個人的には、ループ構造内の実際のインデックス番号を見るのが好きです。0..6おそらくそれは、私が知っているPerl の構文をより連想させるため(0,1,2,3,4,5,6)です。7 が表示された場合は、その横にある演算子をチェックして、実際にはインデックス 7 に到達していないことを確認する必要があります。

于 2008-10-08T13:03:09.790 に答える
4

Edsger Dijkstraは 1982 年にこれに関する記事を書き、 lower <= i < upper を主張しています。

最小の自然数があります。b) と d) のように下限を除外すると、最小の自然数で始まる部分列の下限が不自然数の領域に強制されます。これは醜いので、a) と c) のように下限については ≤ を優先します。ここで、最小の自然数から始まる部分列を考えてみましょう。上限を含めると、列が縮小して空の値になるまでに、後者が不自然になります。これは醜いので、上限には a) と d) のように < を優先します。慣例 a) が優先されると結論付けます。

于 2008-10-08T21:17:15.593 に答える
3

まず、6 または 7 を使用しないでください。

使用する方が良い:

int numberOfDays = 7;
for (int day = 0; day < numberOfDays ; day++){

}

この場合、使用するよりも優れています

for (int day = 0; day <= numberOfDays  - 1; day++){

}

さらに良い (Java / C#):

for(int day = 0; day < dayArray.Length; i++){

}

さらに良い(C#)

foreach (int day in days){// day : days in Java

}

逆ループは確かに高速ですが、読みにくいため (他のプログラマーがそうでない場合)、回避することをお勧めします。特に C#、Java では...

于 2008-10-08T14:09:39.233 に答える
2

これは、 「間違ったコードを間違って見えるようにする」のカテゴリに直接分類されます。

JavaやC#などのゼロベースのインデックス言語では、index < count条件のバリエーションに慣れています。したがって、この事実上の規則を活用すると、1つずつエラーが発生しやすくなります。

パフォーマンスに関して:メモリフットプリントに値する優れたコンパイラは、問題がないなど、レンダリングする必要があります。

于 2008-10-08T18:36:18.663 に答える
2

この場合は 7 が理にかなっているという意見に同意しますが、6 が重要な場合、たとえば、6 番目のインデックスまでのオブジェクトに対してのみ作用していることを明確にしたい場合は、 <= の方が 6 が見やすくなるので良いです。

于 2008-10-08T13:05:02.843 に答える
2

大学時代にさかのぼると、これら 2 つの操作の CPU での計算時間が似ていることを思い出しました。もちろん、私たちはアセンブリ レベルで話し合っています。

ただし、C# や Java について話している場合、一方が他方よりも高速になるとは本当に思いません。得られる数ナノ秒は、導入する混乱に値しない可能性が最も高いです。

個人的には、ビジネス実装の観点から意味のあるコードを作成し、読みやすいようにします。

于 2008-10-08T13:05:40.453 に答える
2

余談ですが、.Net で配列やその他のコレクションをループすると、

foreach (string item in myarray)
{
    System.Console.WriteLine(item);
}

数値の for ループよりも読みやすくなります。もちろん、これは実際のカウンター Int 自体がループ コードで使用されていないことを前提としています。性能の変化があるかどうかはわかりません。

于 2008-10-08T13:14:41.043 に答える
1

私はいつも好んでいます:

for ( int count = 7 ; count > 0 ; -- count )
于 2008-10-08T13:36:07.147 に答える
1

素晴らしい質問です。私の答え:タイプA('<')を使用する

  • 反復回数がはっきりとわかります(7)。
  • 2つの端点の違いは、範囲の幅です
  • 文字が少ないほど読みやすくなります
  • 多くの場合、最後の要素のインデックスではi < strlen(s)なく要素の総数があるため、均一性が重要です。

もう1つの問題は、この構成全体にあります。に3回i表示されるため、タイプミスの可能性があります。for-loop構文は、何をするかではなく、どのように行うかを示します。私はこれを採用することをお勧めします:

BOOST_FOREACH(i, IntegerInterval(0,7))

これはより明確で、同じasm命令などを実行するようにコンパイルされます。必要に応じて、IntegerIntervalのコードを要求してください。

于 2010-01-11T10:43:58.373 に答える
1

人々が観察したように、あなたが言及した2つの選択肢のどちらにも違いはありません. これを確認するために、JavaScript で簡単なベンチマークを行いました。

結果はこちらでご覧いただけます。ここから明らかでないのは、1 番目と 2 番目のテストの位置を入れ替えると、これら 2 つのテストの結果が入れ替わるということです。これは明らかにメモリの問題です。ただし、反復の順序を逆にした 3 番目のテストは明らかに高速です。

于 2008-10-08T15:47:49.613 に答える
1

誰もが言うように、配列の外側でも 0 インデックスのイテレータを使用するのが通例です。すべてが で始まり で0終わり、n-1下限が常に<=で、上限が常に<である場合、コードを確認するときに考えなければならないことはそれほど多くありません。

于 2008-10-08T16:43:01.653 に答える
1

!=代わりに使用することもできます。そうすれば、初期化でエラーが発生した場合に無限ループが発生し、エラーが早期に認識され、それによって引き起こされる問題がループでスタックすることに制限されます (かなり後で問題が発生して見つからないのではなく)それ)。

于 2008-10-08T13:54:29.000 に答える
1

i<7 と書くのには多くの正当な理由があります。7 回繰り返すループに 7 という数字を入れるのは良いことです。パフォーマンスは事実上同一です。ほとんどの人が i<7 と書いています。読みやすさのために書いている場合は、誰もがすぐに認識できる形式を使用してください。

于 2008-10-08T13:17:07.937 に答える
1

マジックナンバーを使用しないでください。

なんで7なの?(またはそのことについては6)。

使用したい数字に正しい記号を使用してください...

その場合、私はそれを使用する方が良いと思います

for ( int i = 0; i < array.size(); i++ )
于 2008-10-08T14:51:01.007 に答える
1

< を使用する習慣をつけると、配列を繰り返し処理するときに、あなたと読者の両方にとって一貫性が保たれます。誰もが標準的な規則を持つ方が簡単です。また、0 から始まる配列を持つ言語を使用している場合は、< が規則です。

これはほぼ確実に、< と <= のパフォーマンスの違いよりも重要です。最初に機能性と読みやすさを目指し、次に最適化します。

もう 1 つの注意点は、フェッチとインクリメントには一時が必要であり、インクリメントとフェッチには必要ないため、i++ よりも ++i を実行する習慣を身につけたほうがよいということです。整数の場合、コンパイラはおそらく一時的なものを最適化しますが、反復型がより複雑な場合はできない可能性があります。

于 2008-10-08T14:38:07.397 に答える
1

「<」演算子と「<=」演算子はまったく同じパフォーマンス コストです。

「<」演算子は標準であり、ゼロベースのループで読みやすくなっています。

i++ の代わりに ++i を使用すると、C++ ではパフォーマンスが向上しますが、C# ではパフォーマンスが向上しません。Java についてはわかりません。

于 2008-10-08T15:03:41.573 に答える
1

非常に多くの答えがあります...しかし、追加するものがあると思います。

私の好みは、「i」がループで取る値を明確に示すリテラル数値です。したがって、ゼロベースの配列を反復処理する場合:

for (int i = 0; i <= array.Length - 1; ++i)

また、配列を繰り返し処理するのではなく、ループするだけの場合、1 から 7 までのカウントは非常に直感的です。

for (int i = 1; i <= 7; ++i)

可読性は、プロファイリングするまでパフォーマンスよりも優先されます。それまでは、コンパイラまたはランタイムがコードに対して何を行うかがわからない可能性があるためです。

于 2010-09-22T00:12:21.897 に答える
0

どちらでもいいと思いますが、選んだらどちらかを貫いてください。<= の使用に慣れている場合は、< を使用しないようにしてください。その逆も同様です。

私は <= を好みますが、0 から始まるインデックスを使用している場合は、おそらく < を試してみます。それはすべて個人的な好みです。

于 2008-10-08T13:04:28.943 に答える
0

時期尚早の最適化は諸悪の根源です。心配する本当に正当な理由がない限り、読みやすさを重視して<ください<=

于 2008-10-27T20:41:15.950 に答える
0

< であるべきだと私は主張します。

いくつかの単語で十分な場合に、なぜ多くの単語を使用するのでしょうか。1 つのテストは、2 つのテストよりも理解しやすいです。その結果、単体テストと今後の変更が容易になります。

差は小さいですか?はい。しかし、それが保証されていないのに、なぜ複雑さを加える必要があるのでしょうか。

最後に、コードが最初から最適化されている場合、オプティマイザーやインタープリターの実装に依存する必要はありません。アインシュタインの言葉を借りれば、「できる限りシンプルに保ち、それ以上シンプルにしないでください」。

于 2009-05-13T17:04:11.923 に答える
0

結果は意味がありません。

ハードウェアの観点から見ると、<= で loopNumber-1 を使用すると、反復ごとに loopNumber-1 を実行するために 1 つの余分な計算が導入されます。したがって、<= と同じ時間ではないにしても、< の方が時間がかからないと思います。

于 2008-10-08T18:28:36.153 に答える
0

そのイディオムは頻繁に繰り返されるので、私は最初の方法に従います。

for (int index = 0; index < array.length; i++)

文字列 s = oldString.substring(0, numChars);

私は上限が除外されることに慣れており、変更する正当な理由がない限り、そのままにしておくことを好みます。(例 -- 1 ベースのインデックス)

于 2008-10-08T13:47:47.797 に答える
0

最初に読みやすさを追求し、後で最適化します (ただし、正直なところ、顕著な違いは想像できません)。

0 -> K 形式は、配列を 0 ベースにすることによって C# に引き継がれた C のイディオムであることに注意してください。イディオムに従い、最小の驚きの原則に違反しないでください。

于 2008-10-08T13:51:22.280 に答える
0

少なくとも x86 コンパイラとのパフォーマンスの違いはないはずです。私が知る限り、JL と JLE は同時に動作します。また、可読性に関しては、7 つの要素の配列に "<7" を使用することは理にかなっています。

于 2008-10-08T13:39:56.640 に答える
0

厳密に論理的な観点から、同等性をテストする正確な理由< countよりも効率的であると考える必要があります。<= count<=

于 2008-10-08T13:11:18.307 に答える
0

私はこれを好みます:

for (int i = 0; i < 7; i++)

ただし (これは単なる考えです)、配列が 0 ベース (C#、Java) であるか 1 ベース (VB .NET) であるかによって、読みやすさが左右される場合があります。私がこれを言うのは、0 から始まる配列を扱うとき、0-6 が 7 回実行されるという考え方に陥るからです。1-7よりも0-6の方が直感的だと思います。繰り返しになりますが、私は C++、Java、C# のバックグラウンドを持っています。

于 2008-10-08T15:25:44.603 に答える
0

.Size または .Length または size()/length() を使用する .NET のような一部の言語/テクノロジでは、反復するたびにそのプロパティにアクセスするため、変数に割り当てるとパフォーマンス ヒットがわずかに少なくなるため、悪い考えです。

于 2008-10-08T15:27:47.220 に答える
0

速度の違いはありませんが、< は 0 ベースの配列を持つ言語で正しい可能性が高くなります。また、上ではなく下に繰り返したい場合は、次のように言えます。

for (i = 7; --i >= 0; ) ...
于 2008-11-04T22:18:49.367 に答える