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

ЖАНРЫ

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

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

Шрифт:

Вместо того чтобы в функции

vectorNorm
выводить тип результата по аргументам, я решил для него использовать тип
long double
, чтобы терять как можно меньше данных. Если вектор представляет собой набор значений целого типа, маловероятно, что в реальных условиях норма вектора может быть адекватно представлена целым типом.

11.12. Вычисление расстояния между векторами

Проблема

Требуется найти евклидово расстояние между векторами.

Решение

Евклидово расстояние между векторами определяется как квадратный

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

Пример 11.22. Расчет расстояния между двумя векторами

#include <cmath>

#include <iostream>

using namespace std;

template<class Iter_T, class Iter2_T>

double vectorDistance(Iter_T first, Iter_T last, Iter2_T first2) {

 double ret = 0.0;

 while (first != last) {

double dist = (*first++) - (*first2++);

ret += dist * dist;

 }

 return ret > 0.0 ? sqrt(ret) : 0.0;

}

int main {

 int v1[] = { 1, 5 };

 int v2[] = { 4, 9 };

 cout << "distance between vectors (1,5) and (4,9) is ";

 cout << vectorDistance(v1, v1 + 2, v2) << endl;

}

Программа примера 11.22 выдает следующий результат.

distance between vectors (1,5) and (4,9) is 5

Обсуждение

Пример 11.22 реализует прямое решение, которое показывает, как следует писать простую обобщенную функцию в стиле STL. Для расчета расстояний между векторами я мог бы использовать функцию

inner_product
, однако я не стал использовать функтор, потому что это неоправданно усложнило бы решение. Пример 11.23 показывает, как можно рассчитывать расстояние между векторами, применяя функтор и функцию
inner_product
из заголовочного файла
<numeric>
.

Пример 11.23. Расчет расстояния между векторами с использованием функции inner_product

#include <numeric>

#include <cmath>

#include <iostream>

#include <functional>

using namespace std;

template<class Value_T>

struct DiffSquared {

 Value_T operator(Value_T x, Value_T y) const {

return (x - y) * (x - y);

 }

};

template<class Iter_T, class Iter2_T>

double vectorDistance(Iter_T first, Iter_T last, Iter2_T first2) {

 double ret = inner_product(first, last, first2, 0.0L,

plus<double>, DiffSquared<double>);

 return ret > 0.0 ? sqrt(ret) : 0.0;

}

int main {

 int v1[] = { 1, 5 };

 int v2[] = { 4, 9 };

 cout << "distance between vectors (1,5) and (4,9) is ";

 cout << vectorDistance(v1, v1 + 2, v2) << endl;

}

Поскольку

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

11.13. Реализация итератора с шагом

Проблема

Имеются смежные числовые ряды и требуется обеспечить доступ к каждому n-му элементу.

Решение

В примере 11.24 представлен заголовочный файл, реализующий класс итератора с шагом.

Пример 11.24. stride_iter.hpp

#ifndef STRIDE_ITER_HPP

#define STRIDE_ITER_HPP

#include <iterator>

#include <cassert>

template<class Iter_T>

class stride_iter {

public:

 // открытые имена, вводимые typedef

 typedef typename std::iterator_traits<Iter_T>::value_type value_type;

 typedef typename std::iterator_traits<Iter_T>::reference reference;

 typedef typename std::iterator_traits<Iter_T>::difference_type

difference_type;

 typedef typename std::iterator_traits<Iter_T>::pointer pointer;

 typedef std::random_access_iterator_tag iterator_category;

 typedef stride_iter self;

 // конструкторы

 stride_iter : m(NULL), step(0) {};

 stride_iter(const self& x) : m(x.m), step(x.step) {}

 stride_iter(Iter_T x, difference_type n) : m(x), step(n) {}

 // операторы

 self& operator++ { m += step; return *this; }

 self operator++(int) { self tmp = *this; m += step; return tmp; }

 self& operator+=(difference_type x) { m += x * step; return *this; }

 self& operator-- { m -= step; return *this; }

 self operator--(int) { self tmp = *this; m -= step; return trap; }

 self& operator--(difference type x) { m -= x + step; return *this; }

 reference operator[](difference_type n) { return m[n * step]; }

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