template<class In, class In2, class T, class BinOp, class BinOp2>
T inner_product(In first, In last, In2 first2, T init, BinOp op, Binop2 op2) {
while (first != last) {
BinOp(init, BinOp2(*first++, *first2++));
}
return init;
}
Благодаря гибкости реализации функции
inner_product
вы можете ее использовать для многих других целей, а не только для расчета скалярного произведения (например,
ее можно использовать для вычисления расстояния между двумя векторами или для вычисления нормы вектора).
Смотри также
Рецепты 11.11 и 11.12.
11.11. Вычисление нормы вектора
Проблема
Требуется найти норму (т. е. длину) числового вектора.
Решение
Можно использовать функцию
inner_product
из заголовочного файла
<numeric>
для умножения вектора на самого себя, как показано в примере 11.21.
Пример 11.21. Вычисление нормы вектора
#include <numeric>
#include <vector>
#include <cmath>
#include <iostream>
using namespace std;
template<typename Iter_T>
long double vectorNorm(Iter_T first, Iter_T last) {
return sqrt(inner_product(first, last, first, 0.0L));
}
int main {
int v[] = { 3, 4 };
cout << "The length of the vector (3.4) is ";
cout << vectorNorm(v, v + 2) << endl;
}
Программа примера 11.21 выдает следующий результат.
The length of the vector (3,4) is 5
Обсуждение
В примере 11.21 функция
inner_product
из заголовочного файла
<numeric>
используется для вычисления скалярного произведения числового вектора на самого себя. Квадратный корень полученного значения, как известно, является нормой вектора, или длиной вектора.
Вместо того чтобы в функции
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,