Самый высокий элемент (самая высокая действительная часть) в Valarray комплексных чисел в C++
Как я могу распечатать самый высокий элемент Valarray комплексных чисел в C++?
Я пытался с этим кодом, но он возвращает сообщения об ошибках
#include <iostream> // std::cout
#include <valarray>
#include <complex>// std::valarray
typedef std::complex<double> Complex;
typedef std::valarray <Complex > CArray;
int main ()
{
CArray y[5]={{1, 2},{3, 4},{2,0},{7,0},{9,0}};
std::cout << "The max is " << y.max() << '\n';
return 0;
}
Выход:
main.cpp: In function 'int main()':
main.cpp:15:35: error: request for member 'max' in 'y', which is of non-class type 'CArray [5] {aka std::valarray<std::complex<double> > [5]}'
std::cout << "The max is " << y.max() << '\n';
^
Что я делаю не так?
Вторая версия кода Я немного изменил код. Теперь я хотел бы получить весь индекс, соответствующий наивысшему элементу моего Valarray, в моем случае весь индекс, соответствующий элементу {9,0}
Примечание: под "самым высоким элементом" я подразумеваю элемент, имеющий наивысшую действительную часть
новый код:
#include <iostream>
#include <valarray>
#include <complex>
#include <algorithm>
#include <numeric>
typedef std::complex<double> Complex;
typedef std::valarray <Complex > CArray;
int main ()
{
CArray y={{1, 2},{3, 4},{2,0},{9,0},{7,0},{9,0}};
auto max_val = std::accumulate (std::begin(y), std::end(y), *std::begin(y),
[](const Complex& a ,const Complex& b)
{
auto abs_a = abs(a);
auto abs_b = abs(b);
//if(abs_a == abs_b)
// return std::max(arg(a), arg(b));
return std::max(abs_a, abs_b);
}
);
for (std::size_t i =std::begin(y) ; i != std::end(y) ; i++) {
std::cout << "The max is found on index ["<< i <<"]" << max_val<< '\n';
}
return 0;
}
Я получаю следующие ошибки: Вывод:
main.cpp: In function 'int main()':
main.cpp:22:35: error: invalid conversion from 'std::complex<double>*' to 'std::size_t {aka long unsigned int}' [-fpermissive]
for (std::size_t i =std::begin(y) ; i != std::end(y) ; i++) {
^
main.cpp:22:54: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
for (std::size_t i =std::begin(y) ; i != std::end(y) ; i++) {
^
3 ответа
y
это массивvalarray
с, так что вам нужно позвонитьmax
на каждом элементе в этом массиве, а не на самом массиве (который, конечно, не имеет функций-членов).std::complex
это не сопоставимый тип, так что значит иметь "самый высокий" элемент?
Обновление: Что касается вашего редактирования, я думаю, я понимаю, что вы после...
Для самого высокого индекса максимума (по real()
) элемент:
std::size_t max_index(CArray const& y) {
struct acc_t {
double max_value;
std::size_t max_idx, current_idx;
constexpr acc_t next() const { return {max_value, max_idx, current_idx + 1}; }
constexpr acc_t next_with(Complex const c) const {
return {c.real(), current_idx, current_idx + 1};
}
};
return std::accumulate(
std::begin(y), std::end(y), acc_t{},
[](acc_t const acc, Complex const c) {
return c.real() < acc.max_value
? acc.next()
: acc.next_with(c);
}
).max_idx;
}
Или для всех индексов элемента max:
std::vector<std::size_t> max_indices(CArray const& y) {
struct acc_t {
std::vector<std::size_t> max_idcs;
double max_value;
std::size_t current_idx;
constexpr acc_t&& next() {
++current_idx;
return std::move(*this);
}
acc_t&& next_with_current() {
max_idcs.push_back(current_idx++);
return std::move(*this);
}
acc_t&& next_with(Complex const c) {
max_value = c.real();
max_idcs.clear();
return next_with_current();
}
};
return std::accumulate(
std::begin(y), std::end(y), acc_t{},
[](acc_t& acc, Complex const c) {
return c.real() < acc.max_value ? acc.next()
: c.real() > acc.max_value ? acc.next_with(c)
: acc.next_with_current();
}
).max_idcs;
}
Nb ваш код имеет abs
участвует, но я не уверен, почему, так как вы сказали, что вы просто хотели сравнение на основе std::complex<>::real()
так что я пропустил это...
Большая проблема вашего исходного кода заключалась в (как указал Илджарн), что сложное отсутствие operator<
,
Я полагаю, что ваш Complex
должно быть немного сложнее (если вы позволите мне играть словами).
Я предлагаю следующее решение было Complex
вытекают из std::complex<double>
и объявить друга operator< ()
, Один из многих operator< ()
возможный.
#include <iostream>
#include <valarray>
#include <complex>
struct Complex: public std::complex<double>
{
template <typename ... Args>
Complex (const Args & ... args) : std::complex<double>{args...}
{ }
friend bool operator< (const Complex & c1, const Complex & c2)
{
return (c1.real() < c2.real())
|| ((c1.real() == c2.real()) && (c1.imag() < c2.imag()));
}
};
typedef std::valarray <Complex > CArray;
int main ()
{
CArray y { {1.0,2.0}, {3.0,4.0}, {2.0,0.0}, {7.0,0.0}, {9.0,0.0} };
std::cout << "The max is " << y.max() << '\n';
return 0;
}
Если вы принимаете это Complex
может быть шаблонным классом (используя Class<double>
вместо Complex
, вы можете написать более общее решение таким образом (который может быть использован также с комплексом на основе float
а также long double
)
#include <iostream>
#include <valarray>
#include <complex>
template <typename T>
struct Complex: public std::complex<T>
{
template <typename ... Args>
Complex (const Args & ... args) : std::complex<T>{args...}
{ }
friend bool operator< (const Complex & c1, const Complex & c2)
{
return (c1.real() < c2.real())
|| ((c1.real() == c2.real()) && (c1.imag() < c2.imag()));
}
};
typedef std::valarray <Complex<double>> CArray;
int main ()
{
CArray y { {1.0,2.0}, {3.0,4.0}, {2.0,0.0}, {7.0,0.0}, {9.0,0.0} };
std::cout << "The max is " << y.max() << '\n';
return 0;
}
PS: должно работать с C++11 тоже.
PS2: извините за мой плохой английский.
--- Отредактировано, чтобы получить индекс элемента max ---
#include <iostream>
#include <valarray>
#include <complex>
template <typename T>
struct Complex: public std::complex<T>
{
template <typename ... Args>
Complex (const Args & ... args) : std::complex<T>{args...}
{ }
friend bool operator< (const Complex & c1, const Complex & c2)
{
return (c1.real() < c2.real())
|| ((c1.real() == c2.real()) && (c1.imag() < c2.imag()));
}
};
typedef std::valarray <Complex<double>> CArray;
int main ()
{
CArray y { {1.0,2.0}, {3.0,4.0}, {2.0,0.0}, {7.0,0.0}, {9.0,0.0} };
auto m = 0U;
for ( auto i = 1U ; i < y.size() ; ++i)
if ( y[m] < y[i] )
m = i;
std::cout << "The max is found on index ["<< m <<"] and is " << y[m]
<< std::endl;
return 0;
}
С помощью std:: Накопить можно получить макс комплексных чисел в функции Matlab max:
#include <iostream>
#include <valarray>
#include <complex>
#include <algorithm>
#include <numeric>
typedef std::complex<double> Complex;
typedef std::valarray <Complex > CArray;
int main ()
{
CArray y={{1, 2},{3, 4},{2,0},{7,0},{9,0}};
auto max_val = std::accumulate (std::begin(y), std::end(y), *std::begin(y),
[](const Complex& a ,const Complex& b)
{
auto abs_a = abs(a);
auto abs_b = abs(b);
if(abs_a == abs_b)
return std::max(arg(a), arg(b));
return std::max(abs_a, abs_b);
}
);
std::cout << "The max is " << max_val<< '\n';
return 0;
}
Изменить: вопрос отредактирован, и ОП хочет получить индекс максимума действительной части комплексных чисел, поэтому ваш ответ:
#include <iostream>
#include <valarray>
#include <complex>
#include <algorithm>
#include <numeric>
typedef std::complex<double> Complex;
typedef std::valarray <Complex > CArray;
int main ()
{
CArray y={{1, 2},{3, 4},{2,0},{7,0},{9,0}};
std::vector<int> index(y.size());
std::iota( index.begin(), index.end(), 0 );
auto max_index = std::accumulate (std::begin(index), std::end(index), *std::begin(index),
[&](int a ,int b)
{
return y[a].real() > y[b].real() ? a: b;
}
);
std::cout << "index of max is " << max_index<< '\n';
return 0;
}
Редактировать 2: так как @ildjarn упоминал измененный вопрос, хочет получить все индексы, соответствующие наивысшему элементу, поэтому измененный ответ:
#include <iostream>
#include <valarray>
#include <complex>
#include <algorithm>
#include <numeric>
typedef std::complex<double> Complex;
typedef std::valarray <Complex > CArray;
int main ()
{
CArray y={{1, 2},{3, 4},{2,0},{7,0},{9,0}};
std::vector<int> index(y.size());
std::iota( index.begin(), index.end(), 0 );
auto max_index = std::accumulate (std::begin(index), std::end(index), *std::begin(index),
[&](int a ,int b)
{
return y[a].real() > y[b].real() ? a: b;
}
);
std::vector<int> indices;
std::copy_if(std::begin(index), std::end(index), std::back_inserter(indices),
[&](int a)
{
return y[a] == y[max_index];
}
);
for (auto i: indices)
std::cout << "index of max is " << i << '\n';
return 0;
}
Редактировать 3: используя std::max_element самое простое решение, которое у нас есть:
#include <iostream>
#include <valarray>
#include <complex>
#include <algorithm>
#include <numeric>
#include <vector>
typedef std::complex<double> Complex;
typedef std::valarray <Complex > CArray;
int main ()
{
CArray y={{1, 2},{3, 4},{2,0},{9,0},{7,0},{9,0}};
auto max_index = std::max_element (std::begin(y), std::end(y),
[](const Complex& a ,const Complex& b)
{
return a.real() < b.real() ;
}
);
std::cout << "index of first max element is " << max_index-std::begin(y) << '\n';
std::cout << "indices of all matches of max element is: " << "[";
for (auto it= std::begin(y), end = std::end(y); it != end; ++it){
if(it->real() == max_index->real()) {
std::cout << it - std::begin(y) << ' ' ;
}
}
std::cout << "]";
return 0;
}