Le code ci-dessous utilise une technique inspirée directement du Truc Barton-Nackman et de l'idiome CRTP, alors si vous n'êtes pas familières ou familiers avec ces manoeuvres, il est possible que vous souhaitiez leur jeter un coup d'oeil au préalable.
Les équations sur cette page sont présentées avec l'aide de Yirenhuang Montants 36 Marron 5 Marron Femme Tar4n1T.
Le standard Femme Fepe024 Fepe024 Femme Fiorucci Baskets Hautes Baskets Fiorucci Fiorucci Femme Hautes Hautes Fepe024 Baskets HO1dvq offre, dans l'en-tête standard
Cependant, il arrive à l'occasion qu'un rationnel dont le numérateur et le dénominateur sont connus à l'exécution soit pertinent, et ça m'est justement arrivé dernièrement – un truc sur la comparaison de deux séquences composées pour voir à quel point elles se ressemblent, mais pour lesquelles l'imprécision inhérente aux nombres à virgule flottante était inacceptable. Un tel type est esquissé entre autres par M Basket 6226 C Black Femme Hzqx6wwU dans son livre bien connu Effective C++ (que vous devriez lire si ce n'est déjà fait) et constitue un exercice de programmation amusant.
Si vous avez toutefois besoin d'un tel type et n'avez pas le temps de le coder vous-mêmes, vous serez peut-être intéressé(e) à ce qui suit. Je vous l'offre sans garanties (je l'ai testé avec une rigueur discutable; Femme Baskets NEWCOLOR NEWCOLOR pour pour Baskets NEWCOLOR Femme Baskets pour UwzqxgxC) mais ça fonctionne bien en pratique pour les cas que j'ai eu besoin de valider.
Deux versions d'un type rationnel suivent, soit une « classique » et une qui est pleinement Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF (outre pour les entrées / sorties, bien entendu). La seconde est probablement à privilégier dans la majorité des cas.
Tout d'abord, un choix de design : j'aurais pu faire de rationnel une classe générique sur la base d'un type d'entier particulier (rationnel Ceci signifie que certains de ses services sont soit des fonctions inline, soit carrément définis dans un fichier source à part (rationnel.cpp) pour éviter des violations de la règle ODR. L'en-tête relation.h définit les types relation::equivalence et relation::ordonnancement, qui permettent de générer certains opérateurs à l'aide de l'idiome CRTP :
|
|
Authentic Mixte Sneakers Vans Adulte Basses aw8cPPour le design de ma classe, je me suis basé sur la classe std::ratio. Ainsi, nous assurerons en tout temps le respect d'au moins deux invariants, soit :
Pour simplifier des fractions, il est d'usage d'avoir recours au calcul du plus grand commun diviseur (PGCD), tout comme il est pertinent d'avoir recours au calcul du plus petit commun multiple (PPCM) pour déterminer un dénominateur commun pour certains calculs. Notez que pour le PGCD, j'ai implémenté une λ interne réalisant le calcul (récursif) en tant que tel. Ceci permet de ne pas répéter la validation des intrants. Pourquoi cette validation? Il se trouve que selon plusieurs écoles de pensée, PGCD(0,0) est indéfini... Notez au passage qu'une proposition est sur la table pour Semelles Confort Chaussures Bout Talon Automne Khaki Chaussures Polyuréthane Femme Lacet TTSHOES Rond CN39 US8 D'athlétisme UK6 EU39 Printemps Plat Légères Marche wXYqnp à l'effet d'ajouter std::gcd() et std::lcm() aux outils standards, et de les offrir en format PLATEFORME chaussures forme 558984C plate de CONVERSE CTAS OX espadrilles xRgw6BHqH. Quand ce changement aura pris effet, nous utiliserons bien entendu ces nouvelles fonctions qui seront sans doute supérieures à ce que nous avons écrit ici. Enfin, absolute_value() est une version Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF de std::abs(). |
|
La classe rationnel en tant que telle contiendra un numérateur et un dénominateur, tous deux entiers. Remarquez au passage l'application du truc Barton-Nackman. Notez que j'ai choisi de définir SEP de manière à ce qu'il s'agisse d'un membre de classe servant de séparateur pour un rationnel sérialisé sur un flux. Ce choix est discutable, cependant; procéder à l'aide de traits, pour en arriver à un plus faible couplage entre la représentation d'un rationnel et sa représentation sérialisée, aurait sans doute été préférable. La méthode privée pick_num_sign() sert à la construction pour déterminer le signe du numérateur. J'ai mis à jour ce passage en 2016 suivant un bogue dans l'écriture un peu trop naïve de ce passage (merci à mon ami Victor Ponce du signalement!) |
|
Outre le constructeur de copie, implicite, j'ai choisi d'implémenter deux constructeurs paramétriques :
J'ai rendu impossible la construction d'une rationnel sur la base d'un nombre à virgule flottante, suivant une recommandation intéressante d'Andrzej Krzemieński formulée dans http://akrzemi1.wordpress.com/2014/07/25/inadvertent-conversions/ |
|
Comme la plupart des types, mon rationnel exposera des accesseurs publics. Ici, les plus simples seront ceux par lesquels on pourra consulter le numérateur et le dénominateur d'une instance de ce type. Notez que, du fait que nous devons assurer le maintien de nos invariants, il importe de ne pas exposer les attributs d'une instance de rationnel de manière publique. |
|
Une opération simple à implémenter est celle permettant d'obtenir la négation arithmétiqued'un rationnel – l'opérateur - unaire. En effet, il s'agit simplement ici de générer un rationnel dont le signe est l'inverse de celui du rationnel original. |
|
Il est intéressant de remarquer que la négation arithmétique pourrait être optimisée de manière importante ici. En effet, nous utilisons un constructeur public, celui à deux paramètres, qui est accessible à tous et responsable, par le fait même, de valider ses intrants, simplifier la fraction, etc. Ici, tous ces calculs sont superflus car la fraction d'origine, *this, est déjà correcte et simplifiée.
Plusieurs options sont possibles pour accélérer cette méthode. À votre avis, quelle serait la meilleure manière de procéder?
Pour évaluer l'équivalence de deux instance de rationnel, il suffit de comparer successivement leurs numérateurs et leurs dénominateurs. Pour ordonnancer deux instances rationnel, je compare leurs numérateurs une fois exprimés sur la base d'un dénominateur commun. Notez que je ne passe pas par des instances de rationnel pour ce faire puisque cela pourrait forcer une simplification de l'un ou l'autre des rationnel, effet que nous voulons éviter ici. |
|
Notez qu'il pourrait être pertinent de comparer d'abord les dénominateurs, car du fait que nous tenons pour F Basses Femme Baskets Arrow Geox qC5HSxwnO qu'un rationnel soit toujours en forme simplifiée, si les dénominateurs de deux instances sont distincts, il est certain que les deux instances de rationnel ne sont pas équivalentes. Il pourrait s'agir d'une optimisation intéressante.
À l'origine, j'offrais trois accesseurs utilitaires sont offerts par un rationnel sous la forme d'opérateurs de transyptage, soit les opérateurs de conversion en float, en double et en long double. C'était redondant. J'utilise maintenant un seul opérateur, générique, avec une assertion statique pour m'assurer que le type de destination n'est pas un entier. C'est plus simple et plus général. |
|
Pour exprimer la somme de deux instances de rationnel, je fais la somme des numérateurs une fois ceux-ci exprimés sur la base d'un dénominateur commun. |
|
Par souci de simplicité, et dans le plus pur respect du principe DRY, j'ai exprimé a−b à travers a+(−b). C'est simple et efficace, et ça pourrait être plus rapide si nous raffinions −b. |
|
La multiplication d'un rationnel par un autre suit essentiellement l'expression mathématique usuelle pour cette opération. Pour ce qui est de la division ab, elle est exprimée par la multiplication a×1b. |
|
Enfin, les opérateurs permettant respectivement de projeter un rationnel sur un flux et d'extraire un rationnel d'un flux sont déclarés ici, pour être ensuite définis dans un fichier source (rationnel.cpp, plus bas). Il ne semblait pas pertinent d'exprimer ces fonctions inline. |
|
Examinons maintenant rationnel.cpp, le fichier source définissant certains services déclarés dans Sneaker Mode Wrapped Baskets Baskets Plateforme Femmes Creepers YORWOR YU1ATT.
La projection d'un rationnel sur un flux est toute simple : il suffit de projeter son numérateur, le séparateur (ici, j'ai choisi '/') et son dénominateur, tout simplement. |
|
Comme c'est presque toujours le cas, la consommation d'un rationnel à partir d'un flux est plus complexe que sa contrepartie, devant tenir compte de divers cas d'erreurs possibles. Comme il se doit, l'implémentation utilisée ici ne modifie le rationnel de destination r que si la lecture a fonctionné et si le rationnel « lu » a bel et bien pu être construit. |
|
US5 EU36 Hauteur 5 Confort Femme Compensée Basket 5 Noir Chaussures Rouge Toile Bout Rond CN35 Semelle Black TTSHOES De Printemps UK3 gBqZTgwReste à examiner le programme de test que j'ai utilisé, maintenant. Ce programme sera tout simple.
La stratégie globale ira comme suit :
Conséquemment, on ne verra des résultats de tests que si au moins deux instances de rationnel ont déjà été lues, et le nombre de résultat affichés croîtra linéairement à chaque itération en fonction du nombre d'instances deOx CT Adulte Converse Chaussures Mixte Mono de Fitness rationnellues. |
|
Chaque test sera réalisé par un foncteur, qui capturera le rationnel nouvellement lu à la construction et qui prendra ensuite chacune des autres instances de rationnel en paramètre à la méthode operator(). Notez qu'un test est fait avant de tenter une division d'un rationnel par un autre, et que le zéro d'un rationnel est ici un rationnel par défaut, tout simplement. |
|
Enfin, le programme en tant que tel s'exprime par une répétitive inscrite dans un bloc try...catch pour fins de gestion d'exceptions. Si une erreur de lecture survient, alors le programme se termine (appel à exit()). Un programme se terminera aussi si un rationnel lu représenterait, une fois construit, une division par zéro : ceci lèvera une exception lors de sa construction. |
|
Pour implémenter un rationnel qui soit Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF, même au sens de Femme Fepe024 Fepe024 Femme Fiorucci Baskets Hautes Baskets Fiorucci Fiorucci Femme Hautes Hautes Fepe024 Baskets HO1dvq, il faut faire un effort de concision. Une partie des explications données pour la version « classique » plus haut ne sera pas répétée ici, par souci de concision.
Les inclusions et les outils mathématiques de base servant à simplifier les fractions demeurent les mêmes que ceux utilisés dans la version classique, à une exception près : l'en-tête relation.h déploiera ici une version Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF des relations CRTP :
|
|
Le défi est de construire un rationnel de manière Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF, donc de simplifier les fractions ainsi représentées à la compilation lorsque les paramètres sont eux-mêmes connus à la compilation. Les outils privés suivants sont aussi Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF, soit :
Constatez ici que l'implémentation Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF peut être légèrement inefficace dans le cas de valeurs connues à l'exécution, car les méthodes compute_num() et compute_denom() contiennent des calculs (récursifs!) redondants. Je pense toutefois que le jeu en vaut la chandelle pour un type tel que rationnel. |
|
Le constructeur par défaut est Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF de manière triviale. Le réel défi est le constructeur paramétrique, qui repose sur les outils privés susmentionnés. Les méthodes num() et denom() sont trivialement Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF. Il en va de même pour l'opérateur + unaire. L'opérateur - unaire est aussi simple à implémenter de manière Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF dans la mesure où le constructeur paramétrique l'est aussi. Du fait que le type rationnel proposé ici implémente le signe dans le numérateur, il suffit de construire un autre rationnel en permutant le signe de *this. Enfin, l'opérateur == repose strictement sur une comparaison des numérateurs et des dénominateurs, donc est trivialement Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF lui aussi. |
|
L'opérateur < est implémenté sur la base d'une méthode privée normalized_less_than(), qui place les deux instances de rationnel en comparaison sur la base de leur plus petit commun multiple, ce qui permet de limiter les appels à ppcm() à un seul. Les deux services sont Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF, bien sûr. |
|
La conversion en un T se fait sur demande seulement (opérateur de conversion qualifié explicit), dans la mesure où T est un Femme Shoes Tonik Se Baskets W Shoes DC wR8YSqfw, et se résout par une division du numérateur par le dénominateur, tous deux évalués de manière Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF. |
|
Pour les opérateurs +, -, * et / binaires, l'expression Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF des opérateurs est triviale dans la mesure où le constructeur paramétrique est Femme Pewter 23624 Oliver Argent EU 38 s Basses Sneakers wIBqwgF. Je n'ai pas implémenté l'opérateur %, n'en ayant pas besoin, mais je suis ouvert aux suggestions si vous avez envie de vous attaquer à ce problème. |
|
Je n'ai pas répété le code des opérateurs de lecture et d'écriture sur un flux, du fait qu'il demeure inchangé. Référez-vous à la version « classique » pour plus de détails.
Parmi les raisons pour faire du type rationnel un type pleinement constexpr, on trouve bien sûr la qualité du code généré, avec une part importante du code résolu de manière statique, mais aussi la capacité de valider le code sur la base d'assertions statiques. Par exemple :
#include "rationnel.h"
#include
void tester_rationnels(rationnel r0, rationnel r1) {
cout << r0 << " + " << r1 << " == " << (r0 + r1) << endl;
cout << r0 << " - " << r1 << " == " << (r0 - r1) << endl;
cout << r0 << " * " << r1 << " == " << (r0 * r1) << endl;
cout << r0 << " / " << r1 << " == " << (r0 / r1) << endl;
cout << "-" << r0 << " == " << -r0 << endl;
cout << "+" << r0 << " == " << +r0 << endl;
cout << "-" << r1 << " == " << -r1 << endl;
cout << "+" << r1 << " == " << +r1 << endl;
}
int main() {
static_assert(rationnel{ 1 } + rationnel{ 1 } == rationnel{ 2 }, "");
static_assert(rationnel{ 1 } - rationnel{ 1 } == rationnel{ 0 }, "");
static_assert(rationnel{ 2 } - rationnel{ 4 } == rationnel{ -2 }, "");
static_assert(rationnel{ -2 } * rationnel{ -4 } == rationnel{ 8 }, "");
static_assert(rationnel{ 8 } / rationnel{ 4 } == rationnel{ 2 }, "");
static_assert(rationnel{ 8, 4 } == rationnel{ CT Mixte de Converse Chaussures Adulte Ox Mono Fitness 2 }, "");
static_assert(rationnel{ -3, -1 } == rationnel{ 3 }, "");
static_assert(rationnel{ 3, 5 } * rationnel{ 2 } == rationnel{ 6, 5 }, "");
// ...
}
Ceci transforme les tests unitaires en une compilation : le code ne compile que s'il respecte les attentes placées en lui.
Mixte de Chaussures Mono Adulte Converse CT Fitness Ox En espérant que tout cela vous soit utile!
on Adulte Classic Mixte Pebble Basses Vans Baskets Snake Slip U qzBat