2016-07-17 4 views
0

Comment puis-je imprimer l'élément le plus élevé de Valarray de nombres complexes en C++?L'élément le plus élevé (partie réelle la plus élevée) dans Valarray de nombres complexes en C++

J'ai essayé avec ce code, mais il retourne les messages d'erreur

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

Sortie:

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'; 
           ^

Qu'est-ce que je fais mal?

Deuxième version du Code j'ai modifié un peu le code, maintenant je voudrais obtenir tout indice correspondant à l'élément le plus élevé de mon valarray dans mon cas tout indice correspondant à l'élément {} 9,0

Note: par "élément le plus élevé" Je veux dire élément ayant la partie réelle le plus

nouveau code:

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

Je reçois des erreurs suivantes: sortie:

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

Répondre

3
  1. y est un tableau de valarray s, vous devez donc appeler max sur chaque élément de ce tableau, et non pas sur le tableau lui-même (ce qui bien sûr n'a pas de fonctions de membre).
  2. std::complex n'est pas un type comparable, alors qu'est-ce que cela signifie d'avoir un élément "le plus haut"?

Mise à jour: En ce qui concerne votre modifier, je pense que je comprends ce que vous êtes après ...

Pour le plus haut indice de l'élément max (par 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

Ou

pour tous les indices de l'élément 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; 
} 

Online Demo

N.B. votre code a abs impliqué mais je ne sais pas pourquoi puisque vous avez dit que vous vouliez juste la comparaison basée sur std::complex<>::real(), donc j'ai omis cela ...

+0

Comme écrit, y est un tableau de 5 valarrays, mais probablement OP entend un valarray de 5 nombres complexes. –

+0

Par élément le plus élevé, j'entends élément ayant la partie réelle la plus élevée – Serge

+0

@Serge: Mis à jour à nouveau pour prendre en charge _all_ indices (que j'ai raté la première fois que j'ai lu votre édition). – ildjarn

0

en utilisant std :: Accumuler peut obtenir maximum de nombres complexes simillar à la fonction 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; 
} 

Edit: question éditée et OP veut obtenir indice maximum de la partie réelle des nombres complexes pour que votre réponse:

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

Edit 2: comme question modifiée mentionnée de @ildjarn veut obtenir tous les indices correspondant à l'élément le plus élevé réponse ainsi modifiée:

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

Edit 3: en utilisant std :: max_element la solution la plus simple, nous avons:

#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; 
} 
+1

Merci, ça marche. J'ai modifié un peu le code, Maintenant je voudrais obtenir tous les index correspondant à l'élément le plus élevé de mon Valarray dans mon cas tous les index correspondant à l'élément {9,0} Note: par "élément le plus élevé" je veux dire élément avoir la partie réelle la plus élevée – Serge

+0

@Serge réponse mise à jour – rahnema1

0

Le plus gros problème de votre code d'origine était (comme indiqué par Ildjarn) que le manque de operator< complexe.

Je suppose que votre Complex devrait être un peu plus complexe (si vous me permettez le jeu sur les mots).

Je propose la solution suivante étaient Complex dériver de std::complex<double> et déclarer un ami operator<(). L'un des nombreux operator<() possible.

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

Si vous acceptez que Complex peut être une classe basé sur un modèle (en utilisant Class<double> au lieu de Complex, vous pouvez écrire une solution plus générale de cette manière (qui peut être utilisé aussi avec complexe basé sur float et 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: devrait travailler avec 11 C++ trop

ps2:. désolé pour mon mauvais anglais

.

--- Sous la direction pour obtenir l'indice de l'élément 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; 
} 
+1

Cela fonctionne aussi, merci, vous l'anglais est bon pour moi. J'ai modifié un peu le code, maintenant je voudrais obtenir tous les index correspondant à l'élément le plus élevé de mon Valarray dans mon cas tous les index correspondant à l'élément {9,0}. S'il vous plaît voir le code que j'ai collé ci-dessus. – Serge

+0

@Serge - J'ai rejeté votre modification parce que c'était clairement faux; J'ai ajouté une solution possible pour obtenir la valeur maximale et l'index correspondant – max66