Обобщённые численные алгоритмы. STL (часть 14)




Обобщённые численные алгоритмы STL c++Следующую, очень нужную и очень мощную группу алгоритмов STL представляют обобщённые численные алгоритмы (заголовочный файл <numeric>). Это не какие-то особые вычислительные методы, как можно подумать исходя из названия. Это алгоритмы, позволяющие применять общеизвестные библиотечные или свои собственные вычислительные функции ко всей совокупности элементов контейнера. А поскольку так, то и вызываются они подобно всем другим алгоритмам STL. Используются такие обобщённые алгоритмы, главным образом в математических вычислениях применительно к контейнерам, содержащим числовые элементы. Но это совсем не обязательно. И если вас не интересуют численные вычисления (например из области цифровой обработки сигналов), то вы можете просто безболезненно пропустить эту часть изложения…

Перечислим представленные STL обобщённые численные алгоритмы: iota (создание монотонно возрастающей последовательности), accumulate (накопление), inner_product (скалярное произведение), partial_sum (частичная сумма), adjacent_difference (смежная разность).

Иллюстрацию работы лучше всего провести на самом используемом и интуитивно понятном алгоритме accumulate. Этот алгоритм редуцирует (уменьшает размерность) контейнера с накоплением значений. В частности, для простых числовых значений он сворачивает vector<> или list<> до одиночного скалярного результирующего значения.

Алгоритм accumulate (как, впрочем, и большинство других) имеет 2 синтаксические формы:

В 1-й форме (она менее интересная) алгоритм суммирует значения элементов контейнера. Не забываем при этом, что для типа string, например, операция ‘+‘ означает конкатенацию, склеивание). Во 2-й форме алгоритм накапливает результат бинарной операции (функции 2-х переменных), применяемой к накапливаемому значению (аккумулятору) и поочерёдно к каждому элементу контейнера.

Непонятно? Это мощная техника, и сейчас всё станет понятно из примера…

В математической статистике находят применение несколько видов среднего значения для числовой последовательности:

  • Среднее арифметическое:

    sa1

  • Среднее геометрическое:

    sg2

  • Среднее гармоническое:

    sr3

  • Среднее квадратическое:

    sq4

Не станем углубляться в смысл каждого из вариантов. Мы сделаем приложение, которое подсчитывает эти средние и ещё некоторые характеристики (дисперсию, средне квадратичное отклонение) для вводимой числовой последовательности. Входную последовательность вводим либо с терминала, либо перенаправлением из предварительно подготовленного файла данных:

Как легко видеть, каждая из записанных выше сложных математических формул вычисляется всего лишь в одну строку, используя технику обобщённых алгоритмов:

Обобщённые численные алгоритмы stl в c++

Здесь мы можем наблюдать известное соотношение, которое подтверждает корректность наших вычислений. Заключается оно в том, что для любой последовательности чисел среднее арифметическое больше или равно среднего геометрического, которое, в свою очередь, больше или равно среднего гармонического. Причём равенство в этих утверждениях достигается только если все члены числовой последовательности равны между собой:

Обобщённые численные алгоритмы stl в c++

Возвратимся к изучению кода. Первый вызов алгоритма accumulate( b, e, 0. ) демонстрирует 1-ю форму использования: значения контейнера суммируются с начальным значением 0.0.

Предупреждение!: Запись точки в константе начального значения, указывающая, что это вещественное значение — принципиально важна. Без этого код будет компилироваться даже без предупреждений, но выполняться с совершенно неверными и крайне сложно толкуемыми результатами! Это связано с тем, что алгоритмы определены как template, и тип 3-го параметра определит для какого типа данных будут задействованы внутренние операции при накоплении.

Все остальные (4 штуки) вызовы accumulate() используют 2-ю форму вызова – передают 4-м параметром функцию накопления. Как видно из примеров, она принимает параметрами текущее накопленное значение и очередной элемент контейнера. А возвращает результат накапливающей операции. Для наглядности, все накапливающие функции записаны в примере в простом и ясном виде. На практике, чтобы избежать зависимости от типа обрабатываемых данных, их также обычно записывают, как шаблонные функции. Тогда это может выглядеть так:

Наконец, обратите внимание, если не обратили до сих пор, что при накоплении сумм мы используем начальное значение 0 (3-й параметр accumulate() ), а при накоплении произведений, естественно, 1, с соответствующим типом данных.

Рассылка новых уроков по программированию:

Обобщённые численные алгоритмы. STL (часть 14)
Оцени эту статью

Об авторе Olej

Стаж практических программных разработок около 40 лет. Преподаватель международной софтверной компании Global Logic. Постоянный автор публикаций IBM Developer Works. Научный редактор книжного издательства компьютерной литературы "Символ-Плюс", Санкт-Петербург.

Обобщённые численные алгоритмы. STL (часть 14): 2 комментария

  1. Всем привет!
    Сегодня заглянул на онлайн сайты, где раньше смотрел, удивленно нашел что они не работают, то есть их фильмы не транслируют вообще, типо в вашей стране видео запрещенно!
    Теперь фильмы не глянуть онлайн по всюду фильмы удалены, что опять назад на торренты?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *