Чтение онлайн

ЖАНРЫ

C++. Сборник рецептов

Когсуэлл Джефф

Шрифт:

#include <stdexcept>

#include <iostream>

#include <iterator>

using namespace std;

template<class Value_T, class Iter_T>

Value_T computeMean(Iter_T first, Iter_T last) {

 if (first == last) throw domain_error("mean is undefined");

 Value_T sum;

 int cnt = 0;

 while (first != last) {

sum += *first++;

++cnt;

 }

 return sum / cnt;

)

int main {

 cout << "please type in several integers separated by newlines" << endl;

 cout << "and terminated by an EOF character (i.e , Ctrl-Z)" << endl;

 double mean = computeMean<double>(

istream_iterator<int>(cin), istream_iterator<int>);

 cout << "the mean is " << mean << endl;

}

При

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

Возможно, вас удивляет то, что я решил тип, возвращаемый функцией

computeMean
из примера 11.7, передать в качестве параметра шаблона, а не выводить его из типа итератора. Это сделано по той причине, что обычно статистические расчеты выполняются с более высокой точностью, чем точность значений, содержащихся в контейнере. Так, в программном коде примера 11.7 возвращаемое среднее значение набора чисел целого типа имеет тип
double
.

11.4. Фильтрация значений, выпадающих из заданного диапазона

Проблема

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

Решение

Используйте функцию

remove_copy_if
, определенную в
<algorithm>
, как показано в примере 11.8.

Пример 11.8 Удаление из последовательности элементов, значения которых меньше заданного

#include <algorithm>

#include <vector>

#include <iostream>

#include <iterator>

using namespace std;

struct OutOfRange {

 OutOfRange(int min, int max) :

min_(min), max_(max) {}

 bool operator(int x) {

return (x < min_) || (x > max_);

 }

 int min_;

 int max_;

};

int main {

 vector<int> v;

 v.push_back(6);

 v.push_back(12);

 v.push_back(10);

 v.push_back(24);

 v.push_back(30);

 remove_copy_if(v.begin, v.end,

 ostream_iterator<int>(cout, "\n"), OutOfRange(10, 25));

}

Программа

примера 11.8 выдает следующий результат.

12

18

24

Обсуждение

Функция

remove_copy_if
копирует элементы из одного контейнера в другой контейнер (или итератор вывода), игнорируя те элементы, которые удовлетворяют предоставленному вами предикату (вероятно, было бы более правильно назвать функцию
copy_ignore_if
). Однако эта функция не изменяет размер целевого контейнера. Если (как часто бывает) количество скопированных функцией
remove_copy_if
элементов меньше, чем размер целевого контейнера, вам придется уменьшить целевой контейнер с помощью функции-члена
erase
.

Для функции

remove_copy_if
требуется унарный предикат (функтор, который принимает один аргумент и возвращает значение типа
boolean
), который возвращает значение «истина», когда элемент не должен копироваться. В примере 11.8 предикатом является объект-функция
OutOfRange
. Конструктор
OutOfRange
принимает нижнюю и верхнюю границу и перегружает оператор
operator
. Функция
operator
принимает параметр целого типа и возвращает значение «истина», если переданный аргумент меньше, чем нижняя граница, или больше, чем верхняя граница.

11.5. Вычисление дисперсии, стандартного отклонения и других статистических функций

Проблема

Требуется рассчитать значение одной или нескольких обычных статистических функций, например дисперсии (variance), стандартного отклонения (standard deviation), коэффициента асимметрии (skew) и эксцесса (kurtosis) для последовательности чисел.

Решение

Функцию

accumulate
из заголовочного файла
<numeric>
можно использовать для расчета многих статистических параметров, а не только для суммирования пользовательских объектов-функций. Пример 11.9 показывает, как можно вычислить значения некоторых важных статистические функций при помощи
accumulate
.

Пример 11.9. Статистические функции

#include <numeric>

#include <cmath>

#include <algorithm>

#include <functional>

#include <vector>

#include <iostream>

using namespace std;

template<int N, class T>

T nthPnwer(T x) {

 T ret = x;

Поделиться с друзьями: