Correction 3:
Structures de contrôle et expressions logiques


Exercice 1: Résolution de polynômes de degré 2 (-, Niveau 0)

Cet exercice ne nécessite pas de corrigé


Exercice 2: MOOC (cours en ligne) (MOOC, Niveau 1)

Cet exercice ne nécessite pas de corrigé

Exercice 3: Quand c'est pas pair c'est impair (if, Niveau 1)

Dans cette exercice, le test sur la parité d'un nombre se fait en examinant le reste de la division entière (opérateur %) par 2 : si ce reste est nul, le nombre est pair. Les tests nécessaires pour vérifier la parité d'un nombre seront faits au moyen de if imbriqués. Dans la ligne 14, on teste si le nombre est nul (c'est le cas le plus simple). Si ce n'est pas le cas nous faisons un premier test pour savoir si le nombre est positif ou négatif (lignes 18 - 23), puis s'il est pair ou impair (lignes 28 - 32).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.util.Scanner;

public class PairImpair {

    public static void main(String[] args) {
        
        Scanner scanner = new Scanner(System.in);
        
        // Demander une valeur à l'utilisateur
        System.out.print("Entrez un nombre entier : ");
        int number = scanner.nextInt();

        // Premièrement, on vérifie si le nombre est zéro, car
        // dans ce cas le test de parité n'est pas nécessaire
        if (number == 0) {
            System.out.println("Le nombre est zéro (et il est pair)");
        } else {
            // S'il n'est pas nul, voyons quel est son signe
            if (number < 0) {
                //Note: System.out.print ne commence pas de nouvelle ligne
                System.out.print("Le nombre est négatif ");
            } else {
                System.out.print("Le nombre est positif ");
            }

            // Teste la parité: si le reste de la division par deux est zéro
            // alors le nombre est pair
            int reste = number % 2;
            if (reste == 0) {
                System.out.println("et pair");
            } else {
                System.out.println("et impair");
            }
        }
        scanner.close();
    }
}


Exercice 4: Dans l'intervalle ... ou pas (if, expressions logiques, Niveau 2)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import java.util.Scanner;

class Intervalle {

    public static void main(String[] args) {
        
        Scanner clavier = new Scanner(System.in);
        
        // demande à l'utilisateur d'entrer un réel
        System.out.print("Entrez un réel : " );
        // déclare x et l'initialise via une interaction clavier
        double x = clavier.nextDouble();

        if ((!(x < 2.0) && (x <  3.0))
                    || (!(x < 0.0) && !(x == 0.0) && ((x <  1.0) || (x ==  1.0)))
                    || (!(x < -10.0) && ((x < -2.0) || (x == -2.0)))) {
            System.out.println("x appartient a I") ;
        } else {
            System.out.println("x n'appartient pas a I");
        }

        clavier.close();
    }
}


Exercice 5: On tourne en rond (Boucles, Portée, Niveau 1)

Exercice 5.3.1

Affichage du programme BouclesFor:

Boucle 1:
0 1 2 3 4 
Boucle 2:
3 4 5 6 7 8 
Boucle 3:
2 1 0 -1 
Boucle 4:
Boucle 5:
0 5 * 1 6 * 
Boucle 6:
0 5 * 1 6 * 2 7 * 3 8 * 4 9 * 5 10 * 6 11 * 7 12 * 8 13 * 9 14 * 10 15 * 
Boucle 7:
3 true * 4 true * 5 true * 6 true * 
Boucle 8:
0 6 * 1 5 * 2 4 * 
Boucle 9: (2 boucles for imbriquées)
0 0 1 2  * 1 0 1 2  * 2 0 1 2  * 
Boucle 10: (boucle "infinie", tapez <ctrl-c> pour l'interrompre)
3 2 1 0 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13     etc ...

.. bon la dernière boucle n'est pas si infinie que ça en réalité puisqu'elle pourra s'arrêter lorsque la valeur de i dépassera la valeur maximale possible pour un entier (overflow) et pourra alors "basculer" vers une valeur positive. Essayez ceci pour vous en convaincre:

int i = 3;
for (; i < 15; i--) {
}
System.out.println("Fin de boucle: " + i);
qui donnera:
Fin de boucle: 2147483647

Exercice 5.3.2

Notez pour cet exercice, la tournure particulièrement alambiquée de la séquence de mise à jour de la première boucle (a = a++) : style à éviter absolument, comme indiqué en cours ! En notation postfixée, l'opérateur ++, retourne d'abord la valeur de a puis ensuite incrémente. Lorsque l'on fait a = a++, la variable a "récupère" donc la valeur avant incrémentation... fort laid !

Affichage du programme AffichageBoucles:

Boucle 1
2
3
4
Boucle 2
5
10
20
Boucle 3
12
6
0
-6
-6
Boucle 4
3
Boucle 5
4
Boucle 6
3

Exercice 5.3.3

Boucle 1  : en Java on ne peut pas redéclarer localement (dans la boucle for) une variable déjà déclarée plus globalement (la déclaration du i précédant le for).

Boucle 2  : en Java, une variable déclarée dans le bloc d'initialisation d'une boucle for est locale au corps de la boucle (ne peut être utilisée en dehors). Il y avait le même petit piège que plus haut (un point virgule à la fin de la ligne for (int i = 0; i < 5; ++i); et une indentation sciemment faussée ).

Exercice 5.3.4

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class BouclesEquivalentes {

    public static void main(String[] args) {
        System.out.println("Boucle for :");
        for (int a = 3; a <= 10; a++) {
            System.out.println("a : " + a);
        }

        System.out.println("Boucle while :");
        int b = 3;
        while (b <= 10) {
            System.out.println("b : " + b);
            b++;
        }

        System.out.println("Boucle do..while :");
        int c = 3;
        do {
            System.out.println("c : " + c);
            c = c + 1;
        } while (c <= 10);
    }
}


Exercice 6: Tables de multiplications (for, Niveau 1)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class Tables {

    public static void main(String[] args) {
        System.out.println("     Tables de multiplication");
        for (int i = 2; i <= 10; ++i) {
            // \n est un saut de ligne 
            System.out.println("\n Table de " + i + " :"); 
            for (int j=0; j <= 10; ++j) { 
                System.out.println("    " + i + " * " + j + " = " + i*j); 
            }
        }
    }
}


Exercice 7: L'heure du bilan (algorithme, if, boucles, Niveau 2)

Ici, il fallait noter qu'il n'est pas nécessaire de stocker les montants de chaque mois. On s'intéresse uniquement à faire un certain nombre de calculs/tests sur les montants introduits au fur et à mesure. Par exemple: à chaque fois qu'un montant est introduit, on l'ajoute au total des montants, stocké dans la variable total, et qui va nous servir au calcul de la moyenne. L'algorithme pour trouver le minimum (resp. maximum) est classique: à chaque fois qu'un nouveau montant est introduit on teste si ce montant est plus petit que le minimum déjà connu. Si oui, le minimum connu devient ce montant, sinon il garde sa valeur.

Le minimum connu est ici initialisé à la plus grande valeur possible pour une variable de type int, donnée en Java par Integer.MAX_VALUE. Si on l'initialisait arbitrairement avec une valeur trop petite (par exemple 10), l'algorithme nous retournerait la valeur d'initialisation au lieu du véritable minimum. On procède de manière analogue pour le maximum.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.util.Scanner;

class Bilan {

    private static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        // Lecture du nombre de mois
        System.out.print("Donnez le nombre de mois: ");
        int months = scanner.nextInt();

        int min = Integer.MAX_VALUE;
        int max = 0;
        int total = 0;

        // Lecture des montants, accumulation et valeurs extrêmes
        for (int i = 0; i < months; i++) {
            System.out.print(" Donnez le montant du mois " + (i + 1)  + " (Frs): ");
            int montant = scanner.nextInt();
            total = total + montant;

            if (montant > max) {
                max = montant;
            }

            if(montant < min) {
                min = montant;
            }
        }

        System.out.println("La somme mensuelle moyenne reçue est: " + (total / months));
        System.out.println("Le montant mensuel minimal reçu est: "+ min);
        System.out.println("Le montant mensuel maximal reçu est: "+ max);
    }
}


Exercice 8: Plus Grand Diviseur Commun (Algorithme, if, boucles, Niveau 2)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.util.Scanner;

class PGDC {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
         
        System.out.println("Calcul du plus grand  diviseur commun de deux nombres entiers positifs.");
        // Entrée des données
        System.out.print("Entrez un nombre positif :  ");
        int nb1 = scanner.nextInt();
        System.out.print("Entrez un nombre positif :  ");
        int nb2 = scanner.nextInt();

        /* 
         * A chaque passage de la boucle while, on modifie le plus grand
         * de a et b en déduisant le nombre plus petit, comme indiqué par
         * la formule d'Euclide. La boucle se terminera quand a et b sont
         * égaux (au pire des cas quand ils valent 1). A ce moment-là, on
         * retourne la valeur de a (on aurait aussi pu retourner b). 
         */
        int a = nb1;
        int b = nb2;

        while (a != b) {
            if (a > b) {
                a = a - b;
            } else {
                b = b - a;
            }
        }

        System.out.println("Le plus grand diviseur commun de " + nb1 + " et " + nb2 + " est " + a);

        scanner.close();
    }
}

Il existe une solution dite récursive du calcul du PGDC un peu plus intuitive à écrire.

Nous verrons la récursion en fin de semestre.


Exercice 9: Permutations et combinaisons (Algorithme, if, boucles, Niveau 2)

La façon intuitive de coder ce programme donne une solution ressemblant à celle-ci :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class CombiPermu {

    public static void main(String[] args) {
        /* Formule mathématique de la permutation de k
         * élements parmi n: (n!)/(n-k)!
         * Formule mathématique de la combinaison de k
         * élements parmi n: (n!)/(k!*(n-k)!)
         */
        //valeurs à définir
        int n = 10;
        int k = 6;

        int n_factorial = 1;
        int k_factorial = 1;
        int n_minus_k_factorial = 1;

        //calcul des factoriels
        for (int i = 1; i <= n; i++) {
            n_factorial *= i;
        }
        for (int i = 1; i <= k; i++) {
            k_factorial *= i;
        }
        for (int i = 1; i <= (n - k); i++) {
            n_minus_k_factorial *= i;
        }

        //permutations
        System.out.println("Le nombre de permutations de " + k
                    + " elements parmi " + n + " est "
                    + (n_factorial / n_minus_k_factorial));

        //combinaisons
        System.out.println("Le nombre de combinaisons de " + k +
                    " elements parmi " + n + " est "
                    + (n_factorial / (k_factorial*n_minus_k_factorial)));
    }
}

Selon les valeurs de n et k les trois boucles calculant les factorielles font des calculs redondants.

Une version du code essayant d'éviter ces redondances serait :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
public class CombiPermu2 {

    public static void main(String[] args) {
        // valeurs à définir
        int n = 10;
        int k = 6;

        int n_factorial, k_factorial, n_minus_k_factorial;
        n_factorial = 1;
        k_factorial = 1;
        n_minus_k_factorial = 1;

        //calcul amélioré des factoriels
        if (k < (n - k)) {
            for (int i = 1; i <= k; i++) {
                k_factorial *= i;
            }
            n_minus_k_factorial = k_factorial;

            for (int i = k + 1; i <= (n - k); i++){
                n_minus_k_factorial *= i;
            }
            n_factorial = n_minus_k_factorial;
            for (int i = (n - k) + 1; i <= n; i++){
                n_factorial *= i;
            }
        } else {
            for (int i = 1; i <= (n - k); i++){
                n_minus_k_factorial *= i;
            }
            k_factorial = n_minus_k_factorial;

            for (int i = (n - k) + 1; i <= k; i++){
                k_factorial *= i;
            }
            n_factorial = k_factorial;

            for (int i = k + 1; i <= n; i++){
                n_factorial *= i;
            }
        }
    
        //permutations
        System.out.println("Le nombre de permutations de " + k
                    + " élements parmi " + n + " est "
                    + (n_factorial / n_minus_k_factorial));
        
        //combinaisons
        System.out.println("Le nombre de combinaisons de " + k
                    + " élements parmi " + n + " est "
                    + (n_factorial / (k_factorial*n_minus_k_factorial)));
    }
}


Exercice 10: Rebonds de balles (for, do while, Niveau 2)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import java.util.Scanner;

public class Rebonds1 {

    public static void main(String[] args) {
        
        Scanner scanner = new Scanner(System.in);
        
        //Constante de gravité
        final double G = 9.81;
        
        // Déclarations
        // vitesses avant et après le rebond
        double v = 0.0;
        double v1 = 0.0;
        // hauteur avant le rebond, hauteur de remontée
        double h = 0.0;
        double h1 = 0.0;
        // hauteur initiale
        double H0 = 0.0;
        // valeur epsilon
        double eps = 0.0;
        // nombre de rebonds
        int NBR = 0;

        /*
         * Entrée des valeurs par l'utilisateur,
         * avec test de validité
         */

        do {
            System.out.print("Coefficient de rebond (0 <= coeff < 1) : ");
            eps = scanner.nextDouble();
        } while ((eps < 0.0) || (eps >= 1.0));
        do {
            System.out.print("Hauteur initiale      (0 <= H0)        : ");
            H0 = scanner.nextDouble();
        } while (H0 < 0.0);
        do {
            System.out.print("Nombre de rebonds     (0 <= N )        : ");
            NBR = scanner.nextInt();
        } while (NBR < 0);

        // Boucle de calcul
        h = H0;
        // on fait une itération par rebond
        for (int nombre = 0; nombre < NBR; ++nombre) {
            v  = Math.sqrt(2.0 * G * h);
            // vitesse après le rebond
            v1 = eps * v;
            // la hauteur à laquelle elle remonte...
            h1 =(v1 * v1) / (2.0 * G);
            // ...qui devient la nouvelle hauteur initiale
            h  = h1;
            System.out.println("rebond " + (nombre+1) + " : " + h);
        }

        /* Affichage du résultat */
        System.out.println("Au " + NBR + "eme rebond, la hauteur sera de " + h + "m.");

        scanner.close();
    }
}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
import java.util.Scanner;

public class Rebonds2 {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);

        //Constante de gravité
        final double G = 9.81;
        // Déclarations
        // vitesses avant et après le rebond
        double v = 0.0;
        double v1 = 0.0;
        // hauteur avant le rebond, hauteur de remontée
        double h = 0.0;
        double h1 = 0.0;
        double h0 = 0.0;
        double eps = 0.0;
        double h_fin = 0.0;

        /*
         * Entrée des valeurs par l'utilisateur,
         * avec test de validité
         */
        do {
            System.out.print("Coefficient de rebond (0 <= coeff < 1) : ");
            eps = scanner.nextDouble();
        } while ((eps < 0.0) || (eps >= 1.0));
        do {
            System.out.print("Hauteur initiale      (0 <= H0)        : ");
            h0 = scanner.nextDouble();
        } while (h0 < 0.0);
        do {
            System.out.println("Hauteur finale  (0 <= h_fin ) : ");
            h_fin = scanner.nextDouble();
        } while (h_fin < 0.0 || h_fin > h0);

        // Boucle de calcul
        h = h0;
        int count = 0;
        do {
            v = Math.sqrt(2.0 * G * h);
            // vitesse après le rebond
            v1 = eps * v;
            // incrémente le nombre de rebonds
            count++;
            // la hauteur à laquelle elle remonte...
            h1 = (v1 * v1) / (2.0 * G);
            // ...qui devient la nouvelle hauteur initiale
            h  = h1;

            System.out.println("rebond " + count + " : " + h );
        } while (h1 > h_fin);

        // Affichage du résultat
        System.out.println("Nombre de rebonds :" + count);

        scanner.close();
    }
}


Exercice 11: MOOC (cours en ligne) (MOOC, Niveau 2)

Cet exercice ne nécessite pas de corrigé

Exercice 12: Eclipse Tutorial 6 (inutile si vous travaillez avec IntelliJ): Utilisation d'un dévermineur (Eclipse, Niveau 0)

Cet exercice ne nécessite pas de corrigé

Exercice 13: IntelliJ Tutorial 5: Utilisation d'un dévermineur (IntelliJ, Niveau 0)

Cet exercice ne nécessite pas de corrigé

Dernière mise à jour: 06/10/2023  (Revision: 1.2)