• ベストアンサー

ループカウンタを使用せず、配列の全てを足したい

質問です。 配列を使い、その値の合計値を出す際に私はループカウンタを利用して足す手法を 思いつくのですが、それ以外の方法があると聞きました。 ですが、それ以外の方法が思いつかなく質問させてください。 int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int nSum = 0; for ( int i = 0; i < 10; i++ ) { nSum += a[i]; } return nSum; ここでループカウンタを使用せず、配列の全てを足すにはどうしたら良いでしょうか。

質問者が選んだベストアンサー

  • ベストアンサー
  • tea_sheep
  • ベストアンサー率53% (8/15)
回答No.5

C++なら、No1の回答者さんがおっしゃるようにSTLのaccumulateを 使うのが簡単だと思います。 自分で実装するのであればポインタを使って for (int *p=a; p<a+10; p++) {  nSum += *p; } のように書くこともできます。 カウンタのほうが分かりやすくてよいと思いますが。

nana1777
質問者

お礼

なるほど、ポインタをそのまま当てはめ pをインクリメントしていくわけですね! 参考にさせていただきます!

その他の回答 (10)

  • don_go
  • ベストアンサー率31% (336/1059)
回答No.11

配列の最後に終端となるデータを設定して   int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1 };   int nSum = 0;   int *p = a;   for(; *p >= 0; *p++) {     nSum += *p;   } または   while (*p>=0) {     nSum += *p++;   };

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.10

#8 さん > 一番高速という意味では、 > (中略) > だと思います。 確かに.(^^; ループアンローリングという手がありましたね. #9 さん > x86系CPUなら > [(ベースアドレス)+(1要素サイズ)*(オフセット)] > のアドレスに格納されているの値の参照を1クロックで > 行うことができるので、 そうなんですが,要素サイズは 1,2,4,8 バイト限定ですよね. 今回のように要素が基本データ型ならいいんですが,一般の構造体だと使えない場合が多いですね.

  • tea_sheep
  • ベストアンサー率53% (8/15)
回答No.9

少なくともx86系CPUなら [(ベースアドレス)+(1要素サイズ)*(オフセット)] のアドレスに格納されているの値の参照を1クロックで 行うことができるので、ループカウンタを使用することで 遅くなるということはないと思います。 まあ、ループ内で行う処理や最適化の質にもよるでしょうけど。 ループ数が固定なら、コンパイラによってはNo.8のような 形にまで最適化してくれるそうですし。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.8

一番高速という意味では、 int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; return a[0]+a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8]+a[9]; だと思います。 一般に、効率を上げるには汎用性を捨てるのが最も効果的です。

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.7

★あぁ…間違った! ・noocyte さん、ご指摘有り難う御座います。 ●質問者さんへ ・間違い⇒『nSum += *a++;』 ・正しい⇒『nSum += *p++;』 ・以上。すみませんでした。

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.6

#3 です. #5 さんに先に書かれちゃいましたが,これがたぶん一番高速な (少なくとも他の方法より遅くはないはず) 方法です. (なので私はよく使います.) int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int nSum = 0; // 以下,#5 さんと実質的に同じコード const int * const endOfArray = &a[10]; // a[] の直後のアドレスを指す. const int *element = a; // a[] の要素を指す. while(element < endOfArray) nSum += *element++; この方法だと,ループ内の処理は, (どうせやらないといけない,配列要素の参照と nSum への加算を除けば) 次の2つだけです. ・element < endOfArray の判定 ・element++ 他方質問文のように,普通にループカウンタを添字にする方法だと, 次の処理が必要です. ・i < 10 の判定 ・i++ ・i から &a[i] を求める処理.つまり次の2つ.  size_t offset = sizeof(a[i]) * i; // a[] の先頭に対する a[i] のバイト・オフセット  const char *address = (char*)a + offset; // a[i] のバイトアドレス (もっとも,後者はコンパイラが最適化によって  前者のようなコードに変換してくれるかもしれません.) #4 さん > nSum += *a++; a は定数なのでエラーですよ~.(笑)

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★『配列の添え字を使うな!』という事かな? ・それならば、配列をポインタにセットして要素分だけループして加算します。 ・これ以外では、私も思い浮かびません。 ・下にサンプルを載せます。 サンプル: int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int *p = a; int nSum = 0; for ( int i = 0 ; i < 10 ; i++ ){  nSum += *a++; } return nSum; 最後に: ・配列とポインタの学習ですかね。 ・やっぱり『ループカウンタを使用せず』の意味がよく分かりません。 ・とりあえず、上記のサンプルをどうぞ。 ・以上。おわり。

nana1777
質問者

お礼

配列とポインタの学習、その通りです。 使うだけなら、こう使えば動く。としか知らない面が多く それを実際に職業にしている方から、違う方法もあるよ。と言われたもので・・・ 参考にさせていただきます!

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.3

再帰呼び出しを使う方法もあります. int a[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int SumOfArray(const int array[], unsigned nElements) {  return (nElements <= 0) ? 0 :      (array[0] + SumOfArray(array + 1, nElements - 1)); } int main(void) {  int nSum = SumOfArray(a, 10);  printf("nSum = %d\n", nSum);  return 0; } ループカウンタを使う場合に比べて遅いし, 配列の要素数が非常に多いとスタックオーバーフローしてしまいますが. /* 私はCよりも先に Lisp を覚えました.(笑) */

nana1777
質問者

お礼

おー!こんな方法もあるんですね! >ループカウンタを使う場合に比べて遅いし, >配列の要素数が非常に多いとスタックオーバーフローしてしまいますが. 私はまだまだ初心者なので、方法として教えて頂けたのは大変ありがたいです!

noname#38837
noname#38837
回答No.2

>ループカウンタを使用せず というのが配列の要素を指定するのに使わない という意味なら下記のようにすることができます 配列の最後の要素にストッパーとしての値を入れて それを検出するまで加算、という風にすればfor文を使わなくても実現できます -----引用       /* 正数のカウント */       for( i = 0; i < inputCount; i++ ){         if ( *data > 0 ){           sum = sum + *data;           count++;         }         data++;       } http://www.na.rim.or.jp/~m_tanabe/c/pointer8.html -----引用

nana1777
質問者

お礼

>ループカウンタを使用せず というのが配列の要素を指定するのに使わない という意味なら下記のようにすることができます その通りです。言葉が足りずすみません。 引用サイト見てみます!ありがとうございます

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.1

STL オーケーなら template<typename InputIterator, typename Type> Type accumulate( InputIterator first, InputIterator last, Type init );

nana1777
質問者

お礼

なるほど! STL調べてみます!

専門家に質問してみよう