fonction template d'une classe template

fonction template d'une classe template - C++ - Programmation

Marsh Posté le 26-08-2006 à 15:26:03    

Bonjour,
 
J'ai une classe template Fraction<class T> ayant un constructeur

Code :
  1. template<int precision>Fraction<T>(double r)

permettant de creer une fraction dont les membres numerateur et denominateur sont de type T à partir d'un flottant r avec une precision de calcul à 10e-precision.  
Je n'arrive pas à instancier une Fraction à l'aide de ce constructeur. Pourriez-vous m'indiquer la syntaxe à utiliser SVP. J'ai essayé les syntaxes suivantes :  

Code :
  1. Fraction<long><2>(3.14)
  2. Fraction<long>(3.14)<2>
  3. Fraction<long, 2>(3.14)

et aucune ne marche.

Reply

Marsh Posté le 26-08-2006 à 15:26:03   

Reply

Marsh Posté le 26-08-2006 à 17:36:55    

Je pense pas que ca puisse passé.
Essaye plutot de mettre le paramètre Precision dans la liste des paramétres tempalte de la classe, et mets lui une valeur par défaut.
 

Code :
  1. template<class T, int PREC=4> class Fraction
  2. {
  3.    // ...
  4.    Fraction(double r) { ... }
  5. };
  6. Fraction<double> d(1) // precision a 10e-4
  7. Fraction<double,9> d(1) // precision a 10e-9


Reply

Marsh Posté le 26-08-2006 à 23:58:21    

Note que si tu choisis la solution de Joel, il te faut aussi un constructeur (et/ou opérateur de cast) pour transformer des Fraction<T,prec> en Fraction<T>.
 
Une autre solution plus simple finalement est de rendre template une fonction set<T prec>(double).
 
Enfin, si ton compilateur accepte très bien le mot-clé inline, alors n'hésite pas à utiliser inline Fraction(double, const T prec) qui est équivalent.

Reply

Marsh Posté le 27-08-2006 à 00:37:50    

nargy a écrit :


Note que si tu choisis la solution de Joel, il te faut aussi un constructeur (et/ou opérateur de cast) pour transformer des Fraction<T,prec> en Fraction<T>.


Ce qui n'est pas une difficulté en soit ;)
 

nargy a écrit :


Une autre solution plus simple finalement est de rendre template une fonction set<T prec>(double).


 
Et la RAII mon cher :o
 

nargy a écrit :


Enfin, si ton compilateur accepte très bien le mot-clé inline, alors n'hésite pas à utiliser inline Fraction(double, const T prec) qui est équivalent.


 
Non, les paramétres template entiers permettent de faire plus, bien plus (detection de valeur erronée a la compilation, arithmetique statique, selection d'algo a la compilation etc ...)

Reply

Marsh Posté le 27-08-2006 à 00:53:02    

> Et la RAII mon cher :o
Ok dac, dommage que tu ne puisse écrire:
Fraction<long> f=<2>3.14;
 
Sinon, tu peut faire une classe PFraction<T,prec> qui hérite de Fraction<T>, avec les casts nécessaires, et notamment un constructeur Fraction<T>(const PFraction<T,prec>& ).
 
Fraction<long> f=PFraction<2>(3.14);

Reply

Marsh Posté le 27-08-2006 à 01:16:38    

PS: a oui j'oubliais.... il y a un algo qui existe et qui est assez sympa pour avoir une fraction à partir d'un nombre flottant.
 
Je ne m'en souvient pas entièrement, mais la méthode consiste à prendre l'inverse de la partie fractionnaire, et garder la partie entière, jusqu'à obtenir une erreur de calcul (nombre trop petit ou trop grand).
 
3.14: 3 + 0.14
1/0.14= 7 + 0.14286
 
donc 3.14~=~ 3+1/7 = 22/7
 
On peut continuer avec 0.14286-0.14, et jusqu'à obtenir une partie fractionnaire 0 ou un overflow sur les nombres entiers de la fraction.
 
3.14 ~=~ 3 + 1/7 - 1/350 = (22*350-7)/7/50 = 7693/2450

Reply

Marsh Posté le 27-08-2006 à 01:31:42    

C'est bien cet algo que j'utilise. En fait je cherche le meilleur moyen de définir l'arrêt du calcul, dans le cas de pi par exemple. Peut-on savoir si on arrive a un overflow sur un type parametre entier (dans mon cas T) ?

Reply

Marsh Posté le 27-08-2006 à 09:41:29    

Quand tu calcule PI, tu ajoute dans une boucle les nombres d'une série. Donc dans ce cas il est plus facile de repérer l'arrondi de calcul sur les flottants:

Code :
  1. // ...
  2. nouveau_pi=ancien_pi+delta;
  3. ratio=ancien_pi/nouveau_pi;
  4. if(ratio>1-epsilon && ratio<1+epsilon)
  5.   break;
  6. // ...


En constante tu peut mettre un epsilon petit et contrôler la précision, ou carrément:

Code :
  1. if(ancien_pi/nouveau_pi==1) break;


Pour la précision max.
 
Pour detecter un overflow sur un entier de type T, tu vérifie que le résultat est cohérent: par exemple si tu ajoute deux nombres positifs le résultat doit être plus grand que les deux nombres de départ.

Reply

Marsh Posté le 27-08-2006 à 10:23:26    

Reply

Marsh Posté le 27-08-2006 à 13:10:53    

Merci beaucoup pour vos reponses. Je n'avais pensé à utiliser, dans une classe/fonction template, les std::numeric_limits. Je crois que je vais utiliser

Code :
  1. template<class I, class F> class Fraction<I,F>


avec I le type entier des numerateur et denominateur et F le type flottant servant à definir la precision des conversions Fraction<--> flottant.

Reply

Marsh Posté le 27-08-2006 à 13:10:53   

Reply

Marsh Posté le 27-08-2006 à 14:47:44    

nargy a écrit :


Sinon, tu peut faire une classe PFraction<T,prec> qui hérite de Fraction<T>, avec les casts nécessaires, et notamment un constructeur Fraction<T>(const PFraction<T,prec>& ).
 
Fraction<long> f=PFraction<2>(3.14);


 
C'est laid et ca enleve tout interet à la version tempalte qui ici fait office
de polymorphisme statique.

Reply

Marsh Posté le 27-08-2006 à 15:06:07    

> C'est laid et ca enleve tout interet à la version tempalte qui ici fait office de polymorphisme statique.
 
ça correspond au moins au modèle mathématique, alors que dans:

Code :
  1. Fraction<double> d(1) // precision a 10e-4


...la precision a 10e-4 est tout à fait arbitraire -- sortirai-t-elle du chapeau du C++ien?
D'où ma proposition d'algorithme pour une précision maximale par défaut, permettant de ne pas obtenir de résultats mathématiques abbérants.

Reply

Marsh Posté le 27-08-2006 à 18:23:56    

ca se defend, mais autant rester en statqiue et propsoer une startegie modifiable a la compilation et non une hierarchie dynamique.

Reply

Marsh Posté le 27-08-2006 à 19:00:24    

tu ferais sans doute bien de faire des traits.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed