std::sqrt(std::valarray)
С ru.cppreference.net
| Определён в заголовке <valarray>
|
||
template< class T >
valarray<T> sqrt( const valarray<T>& va );
|
||
Для каждого элемента в va вычисляет квадратный корень значения элемента.
Параметры
| va | - | массив значений, к которому применяется операция |
Возвращаемое значение
Массив значений, содержащий квадратные корни значений в va .
Примечания
Неквалифицированная функция (sqrt) используется для выполнения вычислений. Если такая функция недоступна, std::sqrt используется из-за поиска, зависящего от аргументов.
Функция может быть реализована с типом возврата, отличным от std::valarray. В этом случае замещающий тип имеет следующие свойства:
- Все
constфункции-члены std::valarray предоставлены. - std::valarray, std::slice_array, std::gslice_array, std::mask_array и std::indirect_array могут быть сконструированы из замещающего типа.
- Для каждой функции, принимающей
const std::valarray<T>&за исключением begin() и end()(начиная с C++11), идентичные функции, принимающие замещающие типы, должны быть добавлены; - Для каждой функции, принимающей два
const std::valarray<T>&аргумента, идентичные функции, принимающие каждую комбинациюconst std::valarray<T>&и замещающих типов, должны быть добавлены. - Тип возврата не добавляет более двух уровней вложенности шаблонов по сравнению с наиболее глубоко вложенным типом аргумента.
Возможная реализация
template<class T> valarray<T> sqrt(const valarray<T>& va) { valarray<T> other = va; for (T& i : other) i = sqrt(i); return other; // может быть возвращен прокси-объект } |
Пример
Находит все три корня (два из которых могут быть комплексно-сопряженными) нескольких Кубических уравнений одновременно.
Запустить этот код
#include <cassert>
#include <complex>
#include <cstddef>
#include <iostream>
#include <numbers>
#include <valarray>
using CD = std::complex<double>;
using VA = std::valarray<CD>;
// возвращаем все n комплексных корней из заданного комплексного числа x
VA root(CD x, unsigned n)
{
const double mag = std::pow(std::abs(x), 1.0 / n);
const double step = 2.0 * std::numbers::pi / n;
double phase = std::arg(x) / n;
VA v(n);
for (std::size_t i{}; i != n; ++i, phase += step)
v[i] = std::polar(mag, phase);
return v;
}
// возвращает n комплексных корней каждого элемента в v; в выходном valarray сначала
// следует последовательность всех n корней из v[0], затем всех n корней из v[1], и т.д.
VA root(VA v, unsigned n)
{
VA o(v.size() * n);
VA t(n);
for (std::size_t i = 0; i != v.size(); ++i)
{
t = root(v[i], n);
for (unsigned j = 0; j != n; ++j)
o[n * i + j] = t[j];
}
return o;
}
// компаратор чисел с плавающей запятой, допускающий заданную погрешность округления
inline bool is_equ(CD x, CD y, double tolerance = 0.000'000'001)
{
return std::abs(std::abs(x) - std::abs(y)) < tolerance;
}
int main()
{
// ввод коэффициентов для полинома x³ + p·x + q
const VA p{1, 2, 3, 4, 5, 6, 7, 8};
const VA q{1, 2, 3, 4, 5, 6, 7, 8};
// решатель
const VA d = std::sqrt(std::pow(q / 2, 2) + std::pow(p / 3, 3));
const VA u = root(-q / 2 + d, 3);
const VA n = root(-q / 2 - d, 3);
// выделить память для корней: 3 * количество входных кубических полиномов
VA x[3];
for (std::size_t t = 0; t != 3; ++t)
x[t].resize(p.size());
auto is_proper_root = [](CD a, CD b, CD p) { return is_equ(a * b + p / 3.0, 0.0); };
// отсеиваем 6 из 9 сгенерированных корней, оставляя только 3 подходящих корня (на полином)
for (std::size_t i = 0; i != p.size(); ++i)
for (std::size_t j = 0, r = 0; j != 3; ++j)
for (std::size_t k = 0; k != 3; ++k)
if (is_proper_root(u[3 * i + j], n[3 * i + k], p[i]))
x[r++][i] = u[3 * i + j] + n[3 * i + k];
std::cout << "Приведенное кубическое уравнение: Корень 1: \t\t Корень 2: \t\t Корень 3:\n";
for (std::size_t i = 0; i != p.size(); ++i)
{
std::cout << "x³ + " << p[i] << "·x + " << q[i] << " = 0 "
<< std::fixed << x[0][i] << " " << x[1][i] << " " << x[2][i]
<< std::defaultfloat
(Примечание: Согласно правилам перевода, HTML-теги, атрибуты и содержимое тегов не подлежат переводу. Термин "defaultfloat" является специфическим термином C++ и сохраняется в оригинале. В данном случае переводить нечего, так как элемент содержит только технические обозначения.) << '\n';
assert(is_equ(std::pow(x[0][i], 3) + x[0][i] * p[i] + q[i], 0.0));
assert(is_equ(std::pow(x[1][i], 3) + x[1][i] * p[i] + q[i], 0.0));
assert(is_equ(std::pow(x[2][i], 3) + x[2][i] * p[i] + q[i], 0.0));
}
}
Вывод:
Уравнение приведённого кубического уравнения: Корень 1: Корень 2: Корень 3: x³ + (1,0)·x + (1,0) = 0 (-0.682328,0.000000) (0.341164,1.161541) (0.341164,-1.161541) x³ + (2,0)·x + (2,0) = 0 (-0.770917,0.000000) (0.385458,1.563885) (0.385458,-1.563885) x³ + (3,0)·x + (3,0) = 0 (-0.817732,0.000000) (0.408866,1.871233) (0.408866,-1.871233) x³ + (4,0)·x + (4,0) = 0 (-0.847708,0.000000) (0.423854,2.130483) (0.423854,-2.130483) x³ + (5,0)·x + (5,0) = 0 (-0.868830,0.000000) (0.434415,2.359269) (0.434415,-2.359269) x³ + (6,0)·x + (6,0) = 0 (-0.884622,0.000000) (0.442311,2.566499) (0.442311,-2.566499) x³ + (7,0)·x + (7,0) = 0 (-0.896922,0.000000) (0.448461,2.757418) (0.448461,-2.757418) x³ + (8,0)·x + (8,0) = 0 (-0.906795,0.000000) (0.453398,2.935423) (0.453398,-2.935423)
Смотрите также
|
применяет функцию
std::pow
к двум valarray или valarray и значению
(шаблон функции) |
|
|
(C++11)
(C++11)
|
вычисляет квадратный корень (
√
x
)
(функция) |
|
комплексный квадратный корень в области правой полуплоскости
(шаблон функции) |