Вход/Регистрация
Программирование. Принципы и практика использования C++ Исправленное издание
вернуться

Страуструп Бьерн

Шрифт:

{

while (first!=last) {

init = init + *first;

++first;

}

return init;

}

Получив начальное значение

init
, он просто добавляет к нему каждое значение из последовательности
[first:last]
и возвращает сумму. Переменную
init
, в которой накапливается сумма, часто называют аккумулятором (accumulator). Рассмотрим пример.

int a[] = { 1, 2, 3, 4, 5 };

cout << accumulate(a, a+sizeof(a)/sizeof(int), 0);

Этот фрагмент кода выводит на экран число 15, т.е. 0+1+2+3+4+5 (0 является начальным значением). Очевидно, что алгоритм

accumulate
можно использовать для всех видов последовательностей.

void f(vector<double>& vd,int* p,int n)

{

double sum = accumulate(vd.begin,vd.end,0.0);

int sum2 = accumulate(p,p+n,0);

}

Тип результата (суммы) совпадает с типом переменной, которую алгоритм

accumulate
использует в качестве аккумулятора. Это обеспечивает высокую степень гибкости которая может играть важную роль. Рассмотрим пример.

void f(int* p,int n)

{

int s1 = accumulate(p, p+n, 0); // суммируем целые числа в int

long sl = accumulate(p, p+n, long(0)); // суммируем целые числа

// в long

double s2 = accumulate(p, p+n, 0.0); // суммируем целые числа

// в double

}

На некоторых компьютерах переменная типа

long
состоит из гораздо большего количества цифр, чем переменная типа
int
. Переменная типа
double
может представить большие (и меньшие) числа, чем переменная типа
int
, но, возможно, с меньшей точностью. В главе 24 мы еще вернемся к вопросу о диапазоне и точности в вычислениях.

Использование переменной
init
в качестве аккумулятора представляет собой весьма распространенную идиому, позволяющую задать тип аккумулятора.

void f(vector<double>& vd,int* p,int n)

{

double s1 = 0;

s1 = accumulate(vd.begin,vd.end,s1);

int s2 = accumulate(vd.begin, vd.end,s2); // Ой

float s3 = 0;

accumulate(vd.begin, vd.end, s3); // Ой

}

Не забудьте инициализировать аккумулятор и присвоить результат работы алгоритма
accumulate
какой-нибудь переменной. В данном примере в качестве инициализатора использовалась переменная
s2
, которая сама еще не получила начальное значение до вызова алгоритма; результат такого вызова будет непредсказуем. Мы передали переменную
s3
алгоритму
accumulate
(по значению; см. раздел 8.5.3), но результат ничему не присвоили; такая компиляция представляет собой простую трату времени.

21.5.2. Обобщение алгоритма accumulate

Итак, основной алгоритм

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

template<class In, class T, class BinOp>

T accumulate(In first, In last, T init, BinOp op)

{

while (first!=last) {

init = op(init, *first);

++first;

}

return init;

}

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

array<double,4> a = { 1.1, 2.2, 3.3, 4.4 }; // см. раздел 20.9

  • Читать дальше
  • 1
  • ...
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: