3. Чтобы сгенерировать сигнал синусоидальной волны, реализуем небольшое лямбда-выражение, имеющее
n
. Его можно вызывать по мере необходимости, и при каждом вызове оно будет возвращать значение для следующей временной точки синусоидальной волны. Вызов std::generate
заполняет вектор сигнала, а вызов std::copy
копирует все значения из вектора переменных типа double
в вектор переменных типа int
. auto sin_gen ([n{0}] () mutable {
return 5.0 * sin(n++ * 2.0 * M_PI / 100);
});
generate(begin(as), end(as), sin_gen);
copy(begin(as), end(as), begin(ds));
4. Сначала выведем на экран сигналы, чтобы позднее можно было построить для них график:
copy(begin(as), end(as),
ostream_iterator
cout << '\n';
copy(begin(ds), end(ds),
ostream_iterator
cout << '\n';
5. Теперь перейдем к самой ошибке суммы. Используем метод std::inner_product
cout << inner_product(begin(as), end(as), begin(ds),
0.0, std::plus
[](double a, double b) {
return pow(a - b, 2);
})
<< '\n';
}
6. Компиляция и запуск программы приведут к выводу двух длинных строк, содержащих сигналы, и третьей строки, в которой показывается единственное значение — разность сигналов. Эта разность равна 40.889
Как это работает
В данном примере мы решили задачу прохода в цикле по двум векторам, получения разности между их соответствующими значениями, возведения их в квадрат и суммирования этих значений с помощью одного вызова std::inner_product
[](double a,double b) { return pow(a-b,2);}
, принимающее разность аргументов и возводящее ее в квадрат.Взглянув на потенциальную реализацию метода std::inner_product
template
T inner_product(InIt1 it1, InIt1 end1, InIt2 it2, T val,
F bin_op1, G bin_op2)
{
while (it1 != end1) {
val = bin_op1(val, bin_op2(*it1, *it2));
++it1;
++it2;
}
return value;
}
Алгоритм принимает пару итераторов (начальный и конечный) для первого диапазона данных, а также начальный итератор для второго диапазона. В нашем случае они представляют собой векторы, для которых нужно определить ошибку суммы. Следующий символ — исходное значение val
0.0
. Затем алгоритм принимает две бинарные функции, которые называются bin_op1
и bin_op2
.К этому моменту мы понимаем, что данный алгоритм очень похож на std::accumulate
bin_op2(*it1,*it2)
на *it
, то перейдем к алгоритму accumulate
. Поэтому можно считать std::inner_product
версией алгоритма std::accumulate
, которая В нашем случае функция-
pow(a-b,2)
. Для другой функции, bin_op1
, мы выбрали std::plus
, поскольку хотим сложить сразу все значения, возведенные в квадрат. Реализуем отрисовщик множества Мандельброта в ASCII
В 1975 году математик Бенуа Мандельброт (Benoˆt Mandelbrot) придумал термин
Рисунок множества Мандельброта можно сгенерировать путем повторения специальной формулы (рис. 6.8).