Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

comment déclarer un vecteur optionel dans une fonction..

3 réponses
Avatar
Xavier
Bonjour,
Merci tout d'abord pour vos réponses précédentes...
Je sèche sur un tout autre probleme
J'ai une fonction de type :
double DoMoyenne (std::vector<double> Valeurs, std::vector<double> Coef)
Est il possible de la déclarer (prototypage) avec le vector Coef en
paramètre optionel prennant pour valeur par défaut un vecteur vide. J'ai
essayé différents trucs (std::vector<double> Coef(0)...) mais ca ne marche
et je ne trouve pas de réponses sur les faqs.
(Selon les cas j'utilise la fonction pour faire une moyenne ou une moyenne
pondérée..).

Merci pour tout élément de réponse
Xavier

3 réponses

Avatar
Falk Tannhäuser
Xavier schrieb:
double DoMoyenne (std::vector<double> Valeurs, std::vector<double> Coef)
Est il possible de la déclarer (prototypage) avec le vector Coef en
paramètre optionnel prenant pour valeur par défaut un vecteur vide. J'ai
essayé différents trucs (std::vector<double> Coef(0)...) mais ça ne marche
et je ne trouve pas de réponses sur les faqs.


double DoMoyenne(std::vector<double> const& Valeurs,
std::vector<double> const& Coef = std::vector<double>());

(Indépendamment du fait d'ajouter un argument par défaut, il est
conseillé de passer les vecteurs par référence afin d'éviter des copies)

(Selon les cas j'utilise la fonction pour faire une moyenne ou une moyenne
pondérée..).


Dans ce cas-là, il me semble plus judicieux de surcharger la fonction,
vu que l'implémentation dans les deux cas est assez différente :

#include <vector>
#include <numeric>
#include <cassert>

double DoMoyenne(std::vector<double> const& Valeurs)
{
assert(!Valeurs.empty());
return std::accumulate(Valeurs.begin(), Valeurs.end(), 0.0) /
Valeurs.size();
}

double DoMoyenne(std::vector<double> const& Valeurs,
std::vector<double> const& Coef)
{
double Coef_total = std::accumulate(Coef.begin(), Coef.end(), 0.0);
assert(Valeurs.size() == Coef.size() && Coef_total != 0);
return std::inner_product(Valeurs.begin(), Valeurs.end(),
Coef.begin(), 0.0) / Coef_total;
}


Falk

Avatar
James Kanze
On Mar 24, 4:18 pm, "Xavier" wrote:
Bonjour,
Merci tout d'abord pour vos réponses précédentes...
Je sèche sur un tout autre probleme
J'ai une fonction de type :
double DoMoyenne (std::vector<double> Valeurs, std::vector<double> Coef)


Tu es sûr que ce n'est pas :

double doMoyenne( std::vector< double > const& valeurs,
std::vector< double > const& coefs ) ;

Parce que je verais bien une fonction qui calcule la moyenne (et
je suppose que d'après le nom, c'est ce dont il s'agit ici)
prend des tableaux d'une taille assez importante. Je suis en
principe contre l'optimisation prématurée, mais quand même,
copier des vecteurs quand il n'y a pas besoin, au moins qu'on
les sait rélativement petits...

Est il possible de la déclarer (prototypage) avec le vector Coef en
paramètre optionel prennant pour valeur par défaut un vecteur vide.


double doMoyenne( std::vector< double > const& valeurs,
std::vector< double > const& coefs
= std::vector< double >() ) ;

Sans les « const& » si tu veux vraiment la copie.

J'ai
essayé différents trucs (std::vector<double> Coef(0)...) mais ca ne m arche
et je ne trouve pas de réponses sur les faqs.


C'est cependant quelque chose que doit expliquer n'importe quel
texte de débuttant. Bien que, évidemment, ce n'est jamais
vraiment nécessaire ; on arrive à exactement le même résultat
avec :

double doMoyenne( std::vector< double > const& valeurs,
std::vector< double > const& coefs ) ;

inline double doMoyenne( std::vector< double > const& valeurs )
{
return doMoyenne( valeurs, std::vector< double >() ) ;
}

(Selon les cas j'utilise la fonction pour faire une moyenne ou une moyen ne
pondérée..).


Refléchis-y quand même. Je me démande si dans ce cas précis, il
ne faut pas utiliser deux fonctions distinctes. Sinon, je
partirais de la dernière solution proposée, en la modifiant un
peu :

double doMoyenne( std::vector< double > const& valeurs,
std::vector< double > const& coefs ) ;

inline double doMoyenne( std::vector< double > const& valeurs )
{
return doMoyenne( valeurs,
std::vector< double >( valeurs.size(),
1.0 ) ) ;
}

C-à-d que tu n'implémentes que la moyenne pondérée, et que dans
l'absence des coefficients, tu utilises 1.0.

Maintenant, si à la place du code simple et facile à maintenir,
tu veux montrer que tu es vraiment « in », et rouler la
mechanique un peu...

template< typename InputIter1, typename InputIter2 >
typename std::iterator_traites< InputIter1 >::value_type
doMoyenne( InputIter1 vBegin, InputIter1 vEnd,
InputIter2 cBegin, InputIter2 cEnd )
{
typedef typename std::iterator_traites< InputIter1
::value_type
Value ;

Value result = Value() ;
typename std::iterator_traits< InputIter1 >::difference_type
count = 0 ;
while ( vBegin != vEnd ) {
assert( cBegin != cEnd ) ;
result += *vBegin * cBegin ;
++ vBegin ;
++ cBegin ;
++ count ;
}
return result / count ;
}

Ensuite, tu définis un itérateur qui renvoie toujours 1, et tu
t'en sers dans une version de doMoyenne qui n'a que deux
paramètres. (Ça a malgré tout l'avantage que tu n'as jamais
besoin de construire le tableau plein de 1. Si tes tableaux
font quelque millions d'éléments, ça peut être un avantage
important.)

--
James Kanze (Gabi Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
Xavier
Merci a tout deux pour votre réponse et en particulier pour les
développements de James...
Mes bases sont encore a améliorer (const& serait un peu mieux en effet).
J'avais pris doMoyenne pour l'exemple mais j'avais en fait a répartir un
montant selon un échéancier de paiement (valeurs = dates) affectés de coef
(10% tel date,...) ou uniformémement réparti entre les dates (=pas de coef).
Merci.

"James Kanze" a écrit dans le message de news:

On Mar 24, 4:18 pm, "Xavier" wrote:
Bonjour,
Merci tout d'abord pour vos réponses précédentes...
Je sèche sur un tout autre probleme
J'ai une fonction de type :
double DoMoyenne (std::vector<double> Valeurs, std::vector<double> Coef)


Tu es sûr que ce n'est pas :

double doMoyenne( std::vector< double > const& valeurs,
std::vector< double > const& coefs ) ;

Parce que je verais bien une fonction qui calcule la moyenne (et
je suppose que d'après le nom, c'est ce dont il s'agit ici)
prend des tableaux d'une taille assez importante. Je suis en
principe contre l'optimisation prématurée, mais quand même,
copier des vecteurs quand il n'y a pas besoin, au moins qu'on
les sait rélativement petits...

Est il possible de la déclarer (prototypage) avec le vector Coef en
paramètre optionel prennant pour valeur par défaut un vecteur vide.


double doMoyenne( std::vector< double > const& valeurs,
std::vector< double > const& coefs
= std::vector< double >() ) ;

Sans les « const& » si tu veux vraiment la copie.

J'ai
essayé différents trucs (std::vector<double> Coef(0)...) mais ca ne marche
et je ne trouve pas de réponses sur les faqs.


C'est cependant quelque chose que doit expliquer n'importe quel
texte de débuttant. Bien que, évidemment, ce n'est jamais
vraiment nécessaire ; on arrive à exactement le même résultat
avec :

double doMoyenne( std::vector< double > const& valeurs,
std::vector< double > const& coefs ) ;

inline double doMoyenne( std::vector< double > const& valeurs )
{
return doMoyenne( valeurs, std::vector< double >() ) ;
}

(Selon les cas j'utilise la fonction pour faire une moyenne ou une
moyenne
pondérée..).


Refléchis-y quand même. Je me démande si dans ce cas précis, il
ne faut pas utiliser deux fonctions distinctes. Sinon, je
partirais de la dernière solution proposée, en la modifiant un
peu :

double doMoyenne( std::vector< double > const& valeurs,
std::vector< double > const& coefs ) ;

inline double doMoyenne( std::vector< double > const& valeurs )
{
return doMoyenne( valeurs,
std::vector< double >( valeurs.size(),
1.0 ) ) ;
}

C-à-d que tu n'implémentes que la moyenne pondérée, et que dans
l'absence des coefficients, tu utilises 1.0.

Maintenant, si à la place du code simple et facile à maintenir,
tu veux montrer que tu es vraiment « in », et rouler la
mechanique un peu...

template< typename InputIter1, typename InputIter2 >
typename std::iterator_traites< InputIter1 >::value_type
doMoyenne( InputIter1 vBegin, InputIter1 vEnd,
InputIter2 cBegin, InputIter2 cEnd )
{
typedef typename std::iterator_traites< InputIter1
::value_type
Value ;

Value result = Value() ;
typename std::iterator_traits< InputIter1 >::difference_type
count = 0 ;
while ( vBegin != vEnd ) {
assert( cBegin != cEnd ) ;
result += *vBegin * cBegin ;
++ vBegin ;
++ cBegin ;
++ count ;
}
return result / count ;
}

Ensuite, tu définis un itérateur qui renvoie toujours 1, et tu
t'en sers dans une version de doMoyenne qui n'a que deux
paramètres. (Ça a malgré tout l'avantage que tu n'as jamais
besoin de construire le tableau plein de 1. Si tes tableaux
font quelque millions d'éléments, ça peut être un avantage
important.)

--
James Kanze (Gabi Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34