Самый высокий элемент (самая высокая действительная часть) в 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 ответа

Решение
  1. y это массив valarrayс, так что вам нужно позвонить max на каждом элементе в этом массиве, а не на самом массиве (который, конечно, не имеет функций-членов).
  2. 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;
}
Другие вопросы по тегам