Как подвести итог элементов вектора C++?

Каковы хорошие способы найти сумму всех элементов в a std::vector?

Предположим, что у меня есть вектор std::vector<int> vector с несколькими элементами в нем. Теперь я хочу найти сумму всех элементов. Каковы различные пути к тому же?

218
задан noɥʇʎԀʎzɐɹƆ 15 January 2017 в 13:47
поделиться

6 ответов

На самом деле существует довольно много методов.

int sum_of_elems = 0;

C++03

  1. Классический цикл for:

    for(std::vector::iterator it = vector.begin(); it != vector.end(); ++it)
     sum_of_elems += *it;
    
  2. Использование стандартного алгоритма:

    #include 
    
    sum_of_elems = std::accumulate(vector.begin(), vector.end(), 0);
    

    flag

    Будьте осторожны с accumulate. Тип последнего аргумента используется не только для начального значения, но и для типа результата. Если вы поместите туда int, он будет накапливать ints, даже если вектор имеет float. Если вы суммируете числа с плавающей точкой, измените 0 на 0.0 или 0.0f (спасибо nneonneo).

C++11 и выше

  1. Использование std::for_each:

    std::for_each(vector.begin(), vector.end(), [&] (int n) {
     sum_of_elems += n;
    });
    
  2. Использование цикла for на основе диапазона (спасибо Роджеру Пейту):

    for (auto& n : vector)
     sum_of_elems += n;
    
400
ответ дан 23 November 2019 в 04:11
поделиться

Prasoon уже предложил множество различных (и хороших) способов сделать это, ни один из которых не нуждается в повторении здесь. Однако я хотел бы предложить альтернативный подход к скорости.

Если вы собираетесь делать это совсем немного, вы можете рассмотреть возможность «подкласса» вашего вектора, чтобы сумма элементов поддерживалась отдельно (а не на самом деле вектор подкласса что сомнительно из-за отсутствия виртуального деструктора - я говорю больше о классе, который содержит сумму и вектор внутри него, has-a , а не is-a , и предоставляет векторные методы).

Для пустого вектора сумма обнуляется. При каждой вставке в вектор добавляйте вставляемый элемент к сумме. При каждом удалении вычитайте это. По сути, все , что может изменить лежащий в основе вектор, перехватывается, чтобы гарантировать согласованность суммы.

Таким образом, у вас будет очень эффективный метод O (1) для «вычисления» суммы в любой момент времени (просто верните текущую вычисленную сумму). Вставка и удаление займут немного больше времени, поскольку вы скорректируете общее количество, и вы должны принять во внимание это снижение производительности.

Векторы, сумма которых требуется чаще, чем изменение вектора, вероятно, выиграют от этой схемы, поскольку затраты на вычисление суммы амортизируются по всем доступам. Очевидно, что если вам нужна только сумма каждый час, а вектор меняется три тысячи раз в секунду, это не подойдет.

Что-то вроде этого было бы достаточно:

class UberVector:
    private Vector<int> vec
    private int sum

    public UberVector():
        vec = new Vector<int>()
        sum = 0

    public getSum():
        return sum

    public add (int val):
        rc = vec.add (val)
        if rc == OK:
            sum = sum + val
        return rc

    public delindex (int idx):
        val = 0
        if idx >= 0 and idx < vec.size:
            val = vec[idx]
        rc =  vec.delindex (idx)
        if rc == OK:
            sum = sum - val
        return rc

Очевидно, что это псевдокод, и вы можете захотеть иметь немного больше функциональных возможностей, но он показывает основную концепцию.

34
ответ дан 23 November 2019 в 04:11
поделиться

Я пользователь Perl, и у нас есть игра - найти всевозможные способы увеличить переменную... здесь нет ничего особенного. Ответ на вопрос, сколько способов найти сумму элементов вектора в C++, вероятно, бесконечность...

Мои 2 цента:

использование BOOST_FOREACH, чтобы избавиться от уродливого синтаксиса итератора:

sum = 0;
BOOST_FOREACH(int & x, myvector){
  sum += x;
}

итерация по индексам (действительно легко читается).

int i, sum = 0;
for (i=0; i<myvector.size(); i++){
  sum += myvector[i];
}

Этот другой - деструктивный, доступ к вектору как к стеку:

while (!myvector.empty()){
   sum+=myvector.back();
   myvector.pop_back();
}
5
ответ дан 23 November 2019 в 04:11
поделиться

Зачем выполнять суммирование в прямом направлении, если это можно сделать в обратном направлении ? Дано:

std::vector<int> v;     // vector to be summed
int sum_of_elements(0); // result of the summation

Мы можем использовать индексирование в обратном направлении:

for (int i(v.size()); i > 0; --i)
    sum_of_elements += v[i-1];

Мы можем использовать «индексирование в обратном направлении» с проверкой диапазона, считая в обратном порядке (на всякий случай):

for (int i(v.size()); i > 0; --i)
    sum_of_elements += v.at(i-1);

Мы можем использовать обратные итераторы в цикле for:

for(std::vector<int>::const_reverse_iterator i(v.rbegin()); i != v.rend(); ++i)
    sum_of_elements += *i;

Мы можем использовать прямые итераторы, выполняя итерацию назад, в цикле for (ооо, сложно!):

for(std::vector<int>::const_iterator i(v.end()); i != v.begin(); --i)
    sum_of_elements += *(i - 1);

Мы можем использовать Накопить с обратными итераторами:

sum_of_elems = std::accumulate(v.rbegin(), v.rend(), 0);

Мы можем использовать for_each с лямбда-выражением с использованием обратных итераторов:

std::for_each(v.rbegin(), v.rend(), [&](int n) { sum_of_elements += n; });

Итак, как вы можете видеть, существует столько же способов суммирования вектора в обратном направлении, сколько способов суммирования вектора вперед, и некоторые из них гораздо более интересны и предлагают гораздо больше возможность для единичных ошибок.

23
ответ дан 23 November 2019 в 04:11
поделиться

Только C ++ 0x:

vector<int> v; // and fill with data
int sum {}; // or = 0 ... :)
for (int n : v) sum += n;

Это похоже на BOOST_FOREACH, упомянутое в другом месте, и дает такое же преимущество ясности в более сложных ситуациях по сравнению с функторами с отслеживанием состояния, используемыми с accumulate или for_each.

5
ответ дан 23 November 2019 в 04:11
поделиться
#include<boost/range/numeric.hpp>
int sum = boost::accumulate(vector, 0);
15
ответ дан 23 November 2019 в 04:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: