Narzędzia użytkownika

Narzędzia witryny


inner_product

Szablon inner_product

Szablon inner_product oblicza iloczyn skalarny1) dwóch kolekcji. Działanie iloczynu skalarnego może być stanardowe lub zdefiniowane przez użytkownika.
Biblioteka stl dostarcza przeciążonej deklaracji inner_product w dwóch wariantach.

Deklaracja

#include <numeric>	//lokalizacja inner_porduct
 
template <class InputIterator1, class InputIterator2, class T>
   T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, T init); // wariant pierwszy
 
template <class InputIterator1, class InputIterator2, 
          class T,
          class BinaryFunction1,class BinaryFunction2>
   T inner_product(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, 
                   T init, 
                   BinaryFunction1 binary_op1, BinaryFunction2 binary_op2);			// wariant drugi


Wariant pierwszy - iloczyn skalarny euklidesowy

Prostsza z deklaracji inner_product udostępnia inerfejs do obliczenia zwykłego iloczynu skalarnego, znanego z geometrii euklidesowej.

Parametery

  • first1 iterator, który wskazuje na początek kolekcji pierwszej
  • last1 iterator, który wskazuje na koniec kolekcji pierwszej
  • first2 iterator, który wskazuje na początek kolekcji drugiej
  • init wartość początkowa wyniku

Działanie

Funkcja inicjalizuje akumulator a = init, po czym oblicza kolejno w podanych zakresach: a = a + (*it1) ⋅ (*it2) gdzie it1 ∈ [first1, last1) , it2 ∈ [first2, first2 + last1-first1).
Jeśli zakresy kolekcji nie są równe, do obliczeń brany jest krótszy zakres. Zwracany jest oczywiście wynik działania. Funckja inner_product ma złożoność liniową.

Przykład

Prosty przykład użycia inner_product, czyli iloczyn skalarny wektorów:

  vector<int> v1;
  vector<int> v2;
 
  v1.push_back(1);
  v1.push_back(2);   // v1 = [ 1, 2 ]
 
  v2.push_back(2);
  v2.push_back(3);  //  v2 = [ 2, 3 ]
 
  //inner <= (1 + 1*2 )+ 2*3 = 9
  int inner = inner_product(v1.begin(), v1.end(), v2.begin(), 1);	// nie jest to "prawdziwy" iloczyn skalarny, bo inicjalizujemy wartością 1
 
  printVector(cout, v2);
  cout<<"Iloczyn skalarny = "<<inner<<endl;		// Iloczyn skalarny = 9

Wariant drugi - iloczyn skalarny zdefinowany przez użytkownika

Druga z deklaracji inner_product jest poszerzona o dwa parametry:

  • binary_op1 operacja dwuargumentowa, która zastąpi dodawanie
  • binary_op2 operacja dwuargumentowa, która zastąpi mnożenie

Działanie

Funkcja inicjalizuje akumulator a = init, po czym oblicza a = binary_op1( a , binary_op2( (*it1) ,(*it2) ) ) dla podanego zekresu kolekcji. Zakresy iteratorów są takie same jak w pierwszym przypadku.
binary_op1 i binary_op2 muszą być funkcjami lub obiektami funkcyjnymi.

Zdefiniowanie operacji do inner_product

Aby wykorzystać inner_product do obliczania własnego iloczynu skalarnego należy zdefiniować własne operacje binary_op1 i binary_op2. Najłatwiej to zrobić posługując się szablonem binary_operation. W przykładzie w pliku inner_product.cpp zdefiniowana jest funkcja multiplies_conj, która mnoży liczbę zespoloną complex przez liczbę sprzężoną z drugą liczbą.

#include <functional> // szablon binary_function 
template<class _Tp> struct multiplies_conj: public binary_function<_Tp, _Tp, _Tp> {// oblicza specyficzne mnożenie dla liczb zespolonych
 
  _Tp operator()(const _Tp& __x, const _Tp& __y) const {			   // obiekt funkcyjny - przeciążony operator ()
    return __x * conj(__y);							   // własne działanie - tutaj conj - zwraca liczbę sprzężoną do __y
  }
 
};

Wykorzystując operację multiplies_conj oraz operację plus (również pochodną binary_function) łatwo jest już zdefiniować iloczyn skalarny dla wektorów liczb zespolonych:

  #include <complex>		       // liczby zespolone complex
  typedef complex<int> ComplexInt;
 
  vector<ComplexInt> c1;
  vector<ComplexInt> c2;
 
  c1.push_back(ComplexInt(1, 0));
  c1.push_back(ComplexInt(3, 2));      // c1 = [ 1, 3 + 2j]
 
  c2.push_back(ComplexInt(4, 5));
  c2.push_back(ComplexInt(3, -1));     // c2 = [ 4 + 5j, 3 -j]
 
  const ComplexInt complexZero(0, 0);
 
  // complex <=  0 + ( 1*(4-5j) + ( (3+2j)*(3+j) ) ) = 4 + 9 - 2 - 5j + 3j + 6j = 11 +4j
  ComplexInt complexInner = inner_product(c1.begin(), c1.end(), c2.begin(), complexZero,
                                plus<ComplexInt>(), multiplies_conj<ComplexInt>());  //zamiast zwykłego mnożenia - mnożenie przez liczbę sprzężoną
 
  cout<<"Iloczyn skalarny = "<<complexInner<<endl;	//Iloczyn skalarny = (11,4)

Zastosowanie inner_product

Możliwych zastosowań inner_product można wymyśleć tyle, ile jest różnych przestrzeni z działaniem iloczynu skalarnego. Wiele problemów, niekoniecznie matematycznych, można wyrazić w postaci obliczania iloczynu skalarnego. Łatwo na przykład zastosować ten sposób obliczeń do porównywania ciągów znaków, do obliczania dopasowania do wzorca. Operacja iloczynu skalarnego jest dość prosta i szybka, dlatego warto z niej skorzystać w swoich projektach.

Przykładowy kod

Fragmenty kodu użyte w artykule znajdują się w pliku inner_product.cpp. Tam też można znaleźć przykład, jak policzyć kąt pomiędzy wektorami przy pomocy funkcji inner_product.

1) operator przypisujący dwóm argumentom wektorowym z przestrzeni liniowej wartość skalarną
inner_product.txt · ostatnio zmienione: 2008/12/12 21:42 przez joanna