0

如何在 C++ 中打印出复数 Valarray 的最高元素?

我已尝试使用此代码,但它返回错误消息

#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++) {
                                                      ^
4

3 回答 3

3
  1. yvalarrays 的数组,因此您需要调用max该数组中的每个元素,而不是数组本身(当然没有成员函数)。
  2. std::complex不是可比类型,那么拥有“最高”元素是什么意思?

更新:关于你的编辑,我想我明白你在追求什么......

对于 max (by 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;
}

Online Demo

或者对于最大元素的所有索引:

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;
}

Online Demo

注意您的代码abs涉及但我不知道为什么,因为您说您只想比较基于std::complex<>::real(),所以我省略了...

于 2016-07-17T06:51:34.950 回答
0

使用 std::accumulate 可以获得复数的最大值,类似于 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;
}

编辑:问题已编辑,OP希望获得复数实部的最大值索引,因此您的答案:

#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;
}
于 2016-07-17T08:58:03.040 回答
0

您的原始代码的更大问题是(正如 Ildjarn 所指出的)复杂缺乏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,你可以用这种方式编写一个更通用的解决方案(也可以与基于floatand的复杂一起使用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:对不起我的英语不好。

--- 编辑以获取最大元素的索引 ---

#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;
 }
于 2016-07-17T11:46:22.630 回答