4

C++ でループを作成して、6 つの乱数を取得し、それらを配列に格納しました。私がやりたいのは、数値「x」よりも大きい値が得られるまで配列の要素を合計することですが、必ずしもすべての要素を追加せずにこれを実行したいと考えています。目的は、合計が x の値になる最初の要素を見つけることです。

たとえば、配列は[1,2,3,4,5,6]、およびx = 6であるため、私が探しているのは要素[1,2,3]です。

私は標準ライブラリを見て、「valarray」の sum 関数を使用しようとしましたが、これはすべての要素の合計を与えるだけです。これをうまくコーディングする方法についてのアイデアは大歓迎です。

4

9 に答える 9

13

加算を行うファンクターを作成します。

#include <algorithm>
struct SumToo
{
     SumToo(int val):m_val(val),m_sum(0) {}
     int m_val;
     int m_sum;

     bool operator()(int next)
     {
         m_sum += next;
         return m_sum >= m_val;
     }
 };

 int main()
 {
       int data[] = {1,2,3,4,5,6};

       int* find = std::find_if(data,data+6,SumToo(6));
 }
于 2009-05-12T14:21:54.367 に答える
8

合計がしきい値に達するか超えるまで、配列の最初のX要素が必要であると想定しています(質問は少しあいまいでした)。

もしそうなら、私はあなた自身のループなしでそれを行う方法を知りません:

int sum = 0;
int i = 0;
for( ; i < len; ++i ) {
    sum += array[i];
    if( sum >= 6 ) {
        break;
    }
}

これで、「i」には、合計がしきい値に達した、または超えたインデックスが含まれます。

于 2009-05-12T14:18:24.483 に答える
3

ステートフル述語でfind_ifを使用することを提案する回答は避けてください。STLアルゴリズムは述語をコピーしても安全であると想定しているため、ステートフル述語は危険です。この場合、コピーが述語で作成されている場合、それぞれに異なる「現在の合計」があり、必ずしもすべての値に作用するわけではなく、正しい順序で作用するわけでもありません。

特に、述語のoperator()メンバーをconstメンバー関数として実装するソリューションは避けてください。ただし、これはステートフル述語ではないと思わせるため、メンバーに可変のラベルを付けます。これは悪いことです。

単にループして答えを見つける答えのいずれか、またはアキュムレータを使用する答えのいずれかを使用することをお勧めします。これが最も正しい方法です(コードが少し扱いに​​くいように見えても)。

警告はC配列とfind_ifには当てはまらない可能性があることに注意してください。将来危険な状況で誤った解決策を使用してしまう可能性があるため、ステートフル述語が問題を解決する正しい方法であることを知ってほしくありません。

参照:C ++コーディング標準:101ルール、ガイドライン、およびベストプラクティス、アイテム87

于 2009-05-13T10:03:43.500 に答える
2

これがもう少し一般的なバージョンです:

#include <iostream>
#include <algorithm>

// return an iterator _Last such that sum 
// of all elements in the range [_First, _Last)
// satisfies the predicate Func
template<class InIt,
class Ty,
class Fn> inline
InIt accumulate_if(InIt First, InIt Last, Ty Val, Fn Func)
{   
    for (; Func(Val) && First != Last; ++First)
        Val = Val + *First;
    return (First);
}

int main() {
    int num[] = {1, 2, 3, 4, 5, 6};
    int *last = accumulate_if(num, num + sizeof num / sizeof num[ 0 ], 
                              0, std::bind2nd(std::less<int>(), 6));
    std::copy(num, last, std::ostream_iterator<int>(std::cout, "\n"));
    return 0;
}
于 2009-05-12T19:54:20.347 に答える
2

0 以下になるまで、xから数値を 1 つずつ減算します。

あなたが望むように、追加はありません:)

于 2009-05-12T15:53:20.067 に答える
0

さて、私はベクトルを使用します

T addUntil(T array[],size_t len,T thres){
    vector<T> vec = vector_from_array(array,len)
    T sum;
    for (size_t i=0;i< vec.size(),sum<thresh;i++){
          sum+= vec[i];
    }
    return sum;
}

Tには、operator+とoperator<を定義する必要があります。

于 2009-05-12T14:21:03.200 に答える
0

これが機能することを願っています:

/* Returns an index i, given array valarray[0,1..n] and number x where i is an index to valarry such that sum over j of valarray[j] for j = 0 to i > x */
int getFirstSum(int *valarray, int n, int x)
{
   int i = 0;
   int sum = x;
   while(sum > x && i < n)
   {
      i++;
      sum -= valarray[i];
   }
   return i;
}
于 2009-05-13T09:53:16.247 に答える
0

次のようになります。

struct StopAtValue{
  StopAtValue(int sum) : m_sum(sum), m_accumulated(0){}
  bool operator()(int val){
    m_accumulated += val;
    return m_accumulated >= sum;
  }
  int m_sum;
  int m_accumulated;
}


int* pos = std::find_if(&array[0], &array[n], StopAtValue(6));
于 2009-05-12T14:23:41.463 に答える
-1

std::find_if() を実行中の合計を維持するファンクターと一緒に使用し、トップにいる要素を見つけた場合にのみファンクターから true を返すことができます。

例えば:

#include <cstdlib>
#include <algorithm>
#include <functional>
#include <iostream>
#include <string>
using namespace std;

// functor returns true when the running total >= findVal
struct running_total : public unary_function<int, bool>
{
    running_total(int findVal) : findVal_(findVal), runningTtl_(0) {};
    bool operator()(int rhs) const
    {
        runningTtl_ += rhs;
        if( runningTtl_ >= findVal_ )
            return true;
        else
            return false;
    }
private:
    mutable int runningTtl_;
    const int findVal_;
};

int main()
{

    int nums[] = {1, 2, 3, 4, 5, 6};
    size_t count = sizeof(nums)/sizeof(nums[0]);

    const int scanTtl = 6;  // running total to scan to
    int * pos = find_if(&nums[0], &nums[0]+count, running_total(scanTtl));

    cout << "Elements Totaling " << scanTtl << " : ";
    copy(&nums[0], pos+1, ostream_iterator<int>(cout, ", "));

    return 0;
}
于 2009-05-12T14:29:39.780 に答える