Exercice langage C : Programmes avec des Fonctions Mathématiques

ExerciceC-id2822


Exercice 1


#include float pht, pttc; main() { printf("Prix HT ? "); scanf("%f", &pht); pttc = pht * (1 + 19.6 / 100); printf("Prix TTC : %f\n", pttc); }

[1] C'est un exercice tout à fait élémentaire. Notez l'absolue nécessité de mettre l'opérateur & devant la variable pht. Faites des essais et constatez que l'oubli de cet opérateur peut engendrer les erreurs les plus graves (« Erreur de segmentation », etc.).

[2] Si on avait déclaré pht de type double au lieu de float, l'instruction scanf aurait dû s'écrire

    scanf("%lf", &pht);

Faites des essais et constatez que ce programme ne marche pas bien si on oublie ce « l ».

La fonction scanf est donc assez délicate à utiliser ; quand les programmes deviendront plus complexes on ara tendance à l'oublier... A retenir, pour la suite : quand un programme qui utilise scanf ne donne pas le résultat attendu, commencez par valider les appels de scanf. Pour cela il suffit de faire suivre chaque appel de scanf par un printf de contrôle :

    ...
    scanf("%f", &pht);
    printf("pht : %f\n", pht);
    ...

[3] La fonction printf requiert des expressions qui n'ont pas à être nécessairement des variables (contrairement à scanf). On peut donc économiser la variable pttc, en remplaçant les quatre lignes de la fonction mainci-dessus par

    ...
printf("Prix HT ? "); scanf("%f", &pht); printf("Prix TTC : %f\n", pht * (1 + 19.6 / 100)); ...

En efficacité on n'y gagne rien, et le programme n'en devient pas plus facile à lire...

[4] Ceux qui utilisent Dev-C+ auront constaté que la fenêtre d'exécution se ferme à la fin du programme et on n'a pas le temps de lire le résultat. Indiquons une fois pour toutes qu'on corrige cela en écrivant, à la fin de la fonction main :

    ...
    system("pause");
}

system est une fonction standard C qui appelle une commande du système sous-jacent ; pause est une commande du système Windows qui arrête le programme, affiche un message (Appuyez sur une touche pour continuer...) et attend un geste de l'utilisateur : voyez l'image ci-dessous.



[5] Voici l'image d'une exécution de ce programme, par exemple sur Windows :
ExerciceC1-id2822

Vous pensez peut-être que 119.599998 n'est pas le résultat attendu (119.6). Eh bien, c'est décevant mais il faudra vous y faire ! Les nombres flottants utilisés dans les ordinateurs ne sont qu'une piètre imitation des nombres réels des mathématiques, et on ne doit pas en espérer une grande précision. Songez qu'avec le codage habituel des float et des double, la représentation d'un nombre aussi simple que 0.1 n'est pas exacte !

Ici l'erreur n'est pas énorme, si on se limite à deux chiffres après la virgule le résultat est exact. On peut améliorer notre programme en imposant le nombre de décimales voulues :

    ...
printf("Prix TTC : %.2f\n", pttc); ...

Maintenant, le résultat s'affiche ainsi : « Prix TTC : 119.60 »

Exercice 2

Première version du programme (on rappelle que les quatre lignes mises en commentaire ne sont pas prises en considération) :

#include 
#include 

float a, b, mArith, mGeo;

main() {
    a = 2;
    b = 3;

 /* printf("a ? ");
    scanf("%f", &a);
    printf("b ? ");
    scanf("%f", &b); */

    printf("a : %f\n", a);
    printf("b : %f\n", b);
    mArith = (a + b) / 2;
    mGeo = sqrt(a * b);
    printf("moyenne arithmétique : %f\n", mArith);
    printf("moyenne gémétrique   : %f\n", mGeo);
}

La deuxième version est la même, en déplaçant les commentaires :

#include 
#include 

float a, b, mArith, mGeo;

main() {
 /* a = 2;
    b = 3; */

    printf("a ? ");
    scanf("%f", &a);
    printf("b ? ");
    scanf("%f", &b);
 
    printf("a : %f\n", a);
    printf("b : %f\n", b);
    mArith = (a + b) / 2;
    mGeo = sqrt(a * b);
    printf("moyenne arithmétique : %f\n", mArith);
    printf("moyenne gémétrique   : %f\n", mGeo);
}

Notez l'importance des lignes #include, surtout la deuxième. Aussi longtemps qu'on utilise simplement printf et scanf, omettre la directive « #include » est déconseillé mais n'empêche pas le programme de fonctionner.

En revanche (faites des essais), il n'y a pas moyen d'obtenir un résultat juste si on a oublié de mettre la directive « #include ». En effet, en l'absence de toute déclaration à son propos, la fonction sqrt sera considérée comme rendant un int. Or, le codage interne des int et celui des float et double sont différents et la suite du travail ne peut pas être juste.



Exercice 3

Notre principal problème, ici, est de calculer le « quotient par défaut » (appelé aussi quotient de la division euclidienne, le quotient de l'école primaire). Pour faire cela en C il n'y a pas besoin de chercher bien loin : si a et bsont de type entier (intcharshortlong), alors a / b représente ce quotient par défaut. Par exemple, si somme vaut 1234 alors somme / 500 vaut 2, non 2.468.

Donc quotient = somme / 500 est le nombre de billets de 500 qu'il faut donner ; la somme qui reste à rendre ensuite est le reste de la division :

somme = somme - quotient * 500;

ou, plus simplement

somme = somme % 500;  

Il y a plusieurs manières d'organiser ce programme. En voici deux : une très rustique et une assez sophistiquée.

#include 

int somme, quotient;

main() {
    printf("somme ? ");
    scanf("%d", &somme);
    printf("%d = ", somme);
    
    quotient = somme / 500;
    if (quotient != 0)
        printf("%d x 500 + ", quotient);
    somme = somme % 500;
    
    quotient = somme / 200;
    if (quotient != 0)
        printf("%d x 200 + ", quotient);
    somme = somme % 200;
    
    quotient = somme / 100;
    if (quotient != 0)
        printf("%d x 100 + ", quotient);
    somme = somme % 100;
    
    quotient = somme / 50;
    if (quotient != 0)
        printf("%d x 50 + ", quotient);
    somme = somme % 50;
    
    quotient = somme / 20;
    if (quotient != 0)
        printf("%d x 20 + ", quotient);
    somme = somme % 20;
    
    quotient = somme / 10;
    if (quotient != 0)
        printf("%d x 10 + ", quotient);
    somme = somme % 10;
    
    quotient = somme / 5;
    if (quotient != 0)
        printf("%d x 5 + ", quotient);
    somme = somme % 5;
    
    quotient = somme / 2;
    if (quotient != 0)
        printf("%d x 2 + ", quotient);
    somme = somme % 2;
    
    if (somme != 0)
        printf("%d", somme);

    printf("\n");
}

C'est un peu lourd, même si, grâce à la fonction copier-coller des éditeurs actuels, ce programme est vite écrit. La présentation du résultat est décevante car une fois sur deux le résultat affiché se termine par un + sans objet :

somme ? 1949
1949 = 3 x 500 + 2 x 200 + 2 x 20 + 1 x 5 + 2 x 2 +

Voici une version plus « pro » (si vous ne connaissez pas encore les tableaux et la boucle for ignorez cette solution ; vous y reviendrez plus tard) :



#include 

int billets[] = { 500, 200, 100, 50, 20, 10, 5, 2, 1 };
int nBillets = sizeof billets / sizeof billets[0];

main() {
    int somme, quotient, i;

    printf("somme ? ");
    scanf("%d", &somme);
    printf("%d = ", somme);
    
    for (i = 0; i 

A l'exécution les deux programmes proposés se valent ; le premier serait même un poil plus efficace. Le deuxième programme est évidemment plus facile à maintenir : si on veut ajouter ou enlever des coupures il suffit d'ajouter ou enlever des éléments dans la liste qui sert à initialiser le tableau billets.