Le but de cette série d'exercices est de vous faire pratiquer encore plus les fonctions en C++ : prototypage, définition, surcharge, valeurs par défaut...
int main() { int i(10), j(55); char a('B'), b('a'); double x(3.14159), y(1.414); cout << "Avant: i=" << i << " et j=" << j << endl; echange(i,j); cout << "Après: i=" << i << " et j=" << j << endl << endl; cout << "Avant: a=" << a << " et b=" << b << endl; echange(a,b); cout << "Après: a=" << a << " et b=" << b << endl << endl; cout << "Avant: x=" << x << " et y=" << y << endl; echange(x,y); cout << "Après: x=" << x << " et y=" << y << endl; return 0; }Si vos fonctions sont correctes, le programme affichera :
Avant: i=10 et j=55 Après: i=55 et j=10 Avant: a=B et b=a Après: a=a et b=B Avant: x=3.14159 et y=1.41 Après: x=1.41 et y=3.14159
Pour calculer n! (factorielle n), on peut utiliser deux formules différentes :
n! = 1 * 2 * 3 * ... * n
0! (factorielle de zéro) = 1 pour tout entier n>0, n! = n * (n-1)!
Dans un fichier C++, implémentez la fonction :
unsigned int factorielleIterative(unsigned int n)
qui calcule n! en faisant le produit des
n
premiers entiers à l'aide d'une boucle for.
Dans le même fichier, implémentez la fonction:
unsigned int factorielleRecursive(unsigned int n)
qui calcule n! en utilisant cette deuxième
formule. Cette fonction doit
donc faire appel à elle-même pour calculer (n-1)!, sauf si n vaut 0,
auquel cas elle devra retourner 1.
[Remarque : Le corps de la fonction tient en 4 lignes]
En réutilisant la fonction demander_nombre() déjà utilisée plusieurs fois dans les séries précédentes, écrivez, dans la fonction main(), le programme qui demande à l'utilisateur d'entrer un entier naturel n (entre 0 et 12 si vous utilisez des int ou des long int et entre 0 et 20 si vous utilisez des long long int), et affiche n! en faisant une première fois appel à factorielleIterative(), puis dans un second temps à factorielleRecursive().
Pour terminer, on pourra ajouter une boucle demandant à l'utilisateur s'il souhaite recommencer.
Entrez un nombre entier compris entre 0 et 12 : 12 Méthode itérative : 12! = 479001600 Méthode récursive : 12! = 479001600 Voulez-vous recommencer [o/n] ? o Entrez un nombre entier compris entre 0 et 12 : 6 Méthode itérative : 6! = 720 Méthode récursive : 6! = 720 Voulez-vous recommencer [o/n] ? n
Les nombres de Fibonnaci sont définis par la suite :
F(0) = 0 F(1) = 1 F(n) = F(n-1)+ F(n-2) avec n>1
Le but de cet exercice est d'écrire un programme qui calcule la valeur de F(n) selon la définition récursive précédente.
Dans le fichier fibonacci.cc, prototypez puis définissez la fonction
unsigned int Fibonacci(unsigned int n)qui calcule la valeur de F(n) de manière récursive (cette fonction devra donc faire appel à elle-même) sans utiliser de structure de boucle (for, while, etc...) et sans aucune variable locale.
Pour comparaison, voici une manière itérative (i.e. non récursive) de calculer les n premier termes de la suite :
unsigned int FibonacciIteratif(unsigned int n) { unsigned int Fn(0); // stocke F(i) , initialisé par F(0) unsigned int Fn_1(Fn); // stocke F(i-1), initialisé par F(0) unsigned int Fn_2(1); // stocke F(i-2), initialisé par F(-1) if (n > 0) for (unsigned int i(1); i <= n; ++i) { Fn = Fn_1 + Fn_2; // pour n>=1 on calcule F(n)=F(n-1)+F(n-2) Fn_2 = Fn_1; // et on decale... Fn_1 = Fn; } return Fn; }
Note : la méthode récursive est coûteuse en temps de calcul (elle est «exponentielle»), ne lancez pas le calcul pour des nombres trop élevés (disons supérieurs à 40).
Entrez un nombre entier compris entre 0 et 40 : 0 Méthode itérative : F(0) = 0 Méthode récursive : F(0) = 0 Voulez-vous recommencer [o/n] ? o Entrez un nombre entier compris entre 0 et 40 : 1 Méthode itérative : F(1) = 1 Méthode récursive : F(1) = 1 Voulez-vous recommencer [o/n] ? o Entrez un nombre entier compris entre 0 et 40 : 2 Méthode itérative : F(2) = 1 Méthode récursive : F(2) = 1 Voulez-vous recommencer [o/n] ? o Entrez un nombre entier compris entre 0 et 40 : 3 Méthode itérative : F(3) = 2 Méthode récursive : F(3) = 2 Voulez-vous recommencer [o/n] ? o Entrez un nombre entier compris entre 0 et 40 : 7 Méthode itérative : F(7) = 13 Méthode récursive : F(7) = 13 Voulez-vous recommencer [o/n] ? n
Ecrivez un programme calculant la valeur approchée d'une intégrale à l'aide de cette formule, c'est-à-dire par
Pour cela écrivez 3 fonctions :
Note : Vous pourrez trouver ici une démonstration de la formule [lien externe] donnée plus haut.
![]() |
Remarque : | |
Comment faire pour ne pas recompiler le programme pour chaque nouvelle fonction ?
En tant que tel, c'est-à-dire laisser l'utilisateur saisir lui-même
sa formule, cela est beaucoup trop compliqué pour ce cours d'introduction. |
On vous donne la fonction non_et :
bool non_et(bool A, bool B) { return not(A and B); }qui renvoie la valeur de NON(A ET B). Comment écrire le corps des fonctions correspondant aux 3 opérateurs logiques NON, ET et OU:
bool non(bool A) bool et(bool A, bool B) bool ou(bool A, bool B)en utilisant UNIQUEMENT la fonction non_et, sans utiliser de if, ni d'opérateurs logiques or, and, not, ||, &&, ou !.
Commencez par écrire la fonction non à l'aide de non_et. Vous pouvez alors utiliser la fonction non en plus de non_et pour écrire la fonction et. La fonction ou peut s'écrire en utilisant les fonctions non et et.
Pour illustrer l'utilisation de la récursivité dans la recherche d'un élément dans une liste ordonnée, nous allons jouer à un petit jeu :
Pensez très fort à un nombre entre 0 et 100...
voilà !
L'ordinateur doit maintenant le trouver...
Pour ce faire, il pourrait énumérer tous les nombres les uns après les
autres jusqu'à avoir la bonne réponse.
Mais, vous en conviendrez aisément, ce n'est pas une méthode très efficace...
Une autre méthode (plus efficace) est la méthode dite « par dichotomie » : on réduit le champ de recherche à chaque étape et on recommence la recherche sur le nouvel intervalle.
On commence avec la zone complète, puis on choisit un pivot (point central de la zone de recherche). En fonction de la comparaison de ce pivot avec l'élément recherché, plusieurs cas de figures peuvent se présenter:
Dans le fichier dichotomie.cc
unsigned int cherche(unsigned int borneInf, unsigned int borneSup);de sorte qu'elle effectue la recherche dans l'intervalle [borneInf, borneSup]
Cette fonction devra choisir un pivot au milieu de l'intervalle (ou s'arrêter, avec un message d'erreur, si l'intervalle est vide), proposer le pivot à l'utilisateur, puis en fonction de sa réponse (<, > ou =) s'appeler elle-même sur le nouvel intervalle ainsi déterminé, ou arrêter la recherche.
La fonction retourne la valeur trouvée (ou la borne inférieure en
cas d'erreur).
Pensez à un nombre entre 1 et 100. Le nombre est il <, > ou = à 50 ? < Le nombre est il <, > ou = à 25 ? > Le nombre est il <, > ou = à 37 ? < Le nombre est il <, > ou = à 31 ? > Le nombre est il <, > ou = à 34 ? < Le nombre est il <, > ou = à 32 ? > Le nombre est il <, > ou = à 33 ? = Votre nombre était 33.
Vous voyez bien sur cet exemple l'intérêt de la recherche par dichotomie par rapport à la recherche linéaire : 6 questions au lieu de 33 (voire au lieu de 68 si l'on demandait en descendant depuis 100 ;-) ).
On souhaite écrire un programme calculant, de façon approchée, une solution à une équation de type
.
La méthode à mettre en œuvre consiste à déterminer, à partir d’une approximation de la solution, une meilleure solution
, et itérer ainsi jusqu’à ce que la valeur absolue de la différence entre
et
soit « suffisamment petite ».
Le calcul de à partir de
se fait à l’aide de la formule suivante (« méthode de Newton ») :
où est la dérivée de
.
Écrire un programme reseq.cc contenant la définition d'une fonction f (à choix) de prototype double f(double).
Le programme demandera un point de départ à l’utilisateur, itérera la recherche d’une solution à partir de ce point, et affichera le résultat trouvé.
Note : Il n’est pas nécessaire d’utiliser un tableau (de taille fixe ou dynamique) pour résoudre ce problème.
Indication : Pour obtenir la valeur de la dérivée d’une fonction en un point, on s’inspire simplement de sa définition :
dont on calcule une approximation pour une valeur ε donnée (par exemple 10−6 ) : définir la constante globale epsilon de valeur « 1e-6 », puis la fonction double df(double x) calculant la valeur approchée de la dérivée de f au point x par :
(f(x+epsilon)-f(x))/epsilon
La fonction utilisée dans cet exemple est :
Point de depart ? 1.55 au point 1.55 : f(x) = -0.012375 f’(x) = -0.2425 nouveau point = 1.49897 au point 1.49897 : f(x) = 0.000257739 f’(x) = -0.249997 nouveau point = 1.5 au point 1.5 : f(x) = -2.18843e-09 f’(x) = -0.25 nouveau point = 1.5 Solution : 1.5