TD D1 : Boucles conditionnelles WHILE¶

L'objectif de ce notebook est de revoir assez rapidement la notion de répétitions sous la forme de boucle *tant que...*

Il y a de nombreuses façons de réaliser des répétitions en informatique, mais la plus universelle est la boucle while.

La structure d'une boucle conditionnelle en python est la suivante:

!!! note Boucle conditionnelle (simple)

while condition :
    bloc d'instructions

!!!

Exemple 1¶

Dans le TDC1, on a écrit un programme qui demandait à l'utilisateur de saisir un entier entre 1 et 7 et qui affichait le jour de la semaine correspondant :

In [ ]:
# rappel du programme version 1:

semaine = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche']

rep = int(input("Saisir un entier entre 1 et 7 :"))

print(f"Vous avez choisi le {semaine[rep-1]}")

Un problème survient lorsque l'utilisateur saisit un eniter non compris entre 1 et 7, le prgoramme renvoie une erreur. On a un peu amélioré la chose ainsi :

In [3]:
# rappel du programme version 2:

semaine = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche']

rep = int(input("Saisir un entier entre 1 et 7 :"))

if 1<= rep <= 7 :
     print(f"Vous avez choisi le {semaine[rep-1]}")
else :
    print("Vous devez saisir un nombre entier entre 1 et 7")
Saisir un entier entre 1 et 7 :8
Vous devez saisir un nombre entier entre 1 et 7

Cette fois-ci, si l'utilisateur entre un entier non compris entre 1 et 7, le programme affiche un message d'erreur, mais s'arrête. On souhaiterait modifier ce programme pour qu'il demande de saisir le nombre entier tant que la saisie n'est pas comprise entre 1 et 7...

In [2]:
# Programme modifié:

semaine = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche']

rep = int(input("Saisir un entier entre 1 et 7 :"))
while rep<1 or rep>7 :
    print("Vous devez saisir un nombre entier entre 1 et 7")
    rep = int(input("Saisir un entier entre 1 et 7 :"))
    
print(f"Vous avez choisi le {semaine[rep-1]}")
Saisir un entier entre 1 et 7 :8
Vous devez saisir un nombre entier entre 1 et 7
Saisir un entier entre 1 et 7 :5
Vous avez choisi le vendredi

Exemple 2¶

La boucle while est très pratique par exemple pour déterminer des "seuils".

Par exemple, si l'on souhaite résoudre dans $\mathbb N$, l'inéquation $2^n>1\,000\,000$, une méthode consiste à tester toutes les valeurs de l'entier n jusqu'à trouver la première qui convienne. Compléter le programme suivant :

In [3]:
n = 1
while 2**n <= 1000000 : 
    n = n + 1
    
print(f"La plus petite valeur n telle que 2**n>1000000 est n={n}")

# doit afficher : ... est n=20
La plus petite valeur n telle que 2**n>1000000 est n=20

Remarque 1: Noter la syntaxe bien pratique des f-string (la chaine de caractère précédée de la lettre f) pour afficher le résultat...

Remarque 2: on peut bien entendu retrouver ce résultat sans boucle si l'on connait la fonction logarithme népérien :

In [6]:
from math import log # importe la fonction logarithme népérien depuis le module math

print(log(1000000)/log(2))

# affiche : 19.931568569324174
19.931568569324174
Out[6]:
2.0

!!! warning Attention

Pour de telles boucles la condition de l'arrêt doit toujours être posée. Dans le cas précédent, on "sait" que la fonction $n\mapsto 2^n$ est croissante et tend vers l'infini, donc on est assuré qu'à partir d'un certain moment la condition 2**n < 1000000 sera fausse et que la boucle s'arrêtera.

!!!

Exercice 1¶

Q1. Compélter le script suivant qui doit donner le plus petit entier $n$ tel que : $\ln(n)>10$

In [7]:
from math import log as ln # la fonction ln rest maintenant disponible

n=1
while ln(n)<=10 :
    n += 1

print(f"le plus petit entier solution est n={n}")
le plus petit entier solution est n=22027

Exercice 2¶

L'objectif de cet exercice est de résoudre l'inéquation suivante où $n$ est un entier positif: $$ 1+2+3+\ldots+n \geqslant 1000$$

Q2. Compléter le script suivant pour résoudre cette inéquation.

In [8]:
somme = 0
n = 0

while somme <= 1000 :
    n = n+1
    somme = somme + n
    

print(f"solution : tous les entiers supérieurs ou égaux à {n}")
solution : tous les entiers supérieurs ou égaux à 45

Solution : n = # à compléter


Exercice 3 (épargne)¶

Q3. Imaginons que l'on dispose initialement sur un compte épargne d'une somme de 1000 €. Sachant que cette somme augmente de 3% par an, compléter le script python dans la cellule suivante pour savoir après combien d'années on aura doublé notre investissement.

In [1]:
n = 0
capital = 1000
taux = 0.03

while capital < 2000 :
    capital *= 1+taux
    n += 1

print(f"le capital double apres {n} années")
le capital double apres 24 années

Réponse : au taux de 3%, il faut 24 pour doubler son capital


Exercice 4 (remboursement crédit)¶

Vous empruntez un capital de somme=100 000 € à la banque au "taux global de taux=2%". Pour simplifier un peu on va considérer que vous faites des remboursements annuels de remb=4 500 € (soit un peu moins de 400 euros par mois). Le principe est le suivant : tous les ans la somme qu'il vous reste à rembourser est augmentée de 2% puis diminuée de 4500 €. Notons n le nombres d'années nécessaires pour rembourser ce crédit. On a ainsi :

  • pour n=0, somme = 100 000
  • pour n=1, somme = 100 000*1.02 - 4500 = 97 500
  • pour n=2, somme = 97 500*1.02 - 4500 = 94 950

Q4. Compléter le script suivant pour afficher après combien d'années le crédit aura été remboursé :

In [2]:
somme =100000
taux = 0.02
remb = 4500
n = 0

while somme >0 :
    somme = somme*(1+taux)-remb
    n += 1

print(f"Le crédit sera remboursé après {n} années")
Le crédit sera remoursé après 30 années

Réponse : Il faut 30 ans pour rembourser son crédit

Q5a. Au final quel est le montant total de votre remboursement ? (utilisez la cellule de code ci-dessous pour faire le calcul !)

In [4]:
n*remb
Out[4]:
135000

Réponse : On a remboursé au total 135 000 euros

Q5b. Du coup, quel a été le coup de ce crédit ?

In [6]:
n*remb-100000
Out[6]:
35000

Réponse : le crédit nous a couté 35000 euros (soit 35% de la somme prếtée !)

Q6. Recopier votre script précédent de Q4. ci-dessous et passer le taux à 5%. Que se passe-t-il ?

In [ ]:
# on remplace taux par 0.05

Réponse : La boucle devient infinie, la dette augmente plus vite que le remboursement !! Aïe aïe aïe !

Exercice 5¶

Q7. Aller sur la page de boucles while de coding game lire le cours et faire les QCM.


Pour les plus rapides !

Exercice 6 : la suite de Syracuse¶

La suite de Syracuse est définie de la façon suivante:

!!! note principe de construction de la suite de Syracuse

« On part d'un entier $u_0$. Si cet entier est pair on note $u_1$ la moitié de $u_0$ et s'il est impair on prend pour $u_1$ le triple de $u_0$ auquel on ajoute 1. On recommence alors le procédé avec $u_1$ pour trouver $u_2$ et ainsi de suite... » !!!

Q8. On rappelle les instructions python permettant d'effectuer une division euclidienne :

  • a // b : donne le quotient (entier) de la division (euclidienne) de a par b. Par exemple 13//2 donne 6.
  • a % b : donne le reste de la division euclidienne de a par b. Par exemple 13 % 2 donne 1. (Cela pourrait servir à déterminer si un nombre est pair ou pas...)

(Remarque, si on n'y arrive pas, on peut utiliser ChatGPT ou Gemini pour demander comment on fait pour déterminer si un nombre est pair en python...)

Écrire alors un script python qui affiche les termes $u_0$ à $u_{20}$ si l'on part de $u_0=13$.

In [7]:
# Afficher les 20 premiers termes de la suite de Syracuse avec u0 = 13

u = 13
n = 0
while n < 20 :
    print(f"u({n})={u}")
    n += 1
    if u%2 == 0 :
        u = u//2
    else :
        u = 3*u + 1
u(0)=13
u(1)=40
u(2)=20
u(3)=10
u(4)=5
u(5)=16
u(6)=8
u(7)=4
u(8)=2
u(9)=1
u(10)=4
u(11)=2
u(12)=1
u(13)=4
u(14)=2
u(15)=1
u(16)=4
u(17)=2
u(18)=1
u(19)=4

Q9. Une conjecture célèbre prédit que quelle que soit la valeur de $u_0$ choisie, on finit toujours par tomber sur un terme $u_n$ qui vaudra 1. On s'interresse à la suite de Syracuse partant de $u_0=19$. Écrire un script python qui affiche tous les termes jusqu'à obtenir 1. Il doit aussi donner le nombre de termes calculés (on appelle cela la durée du vol).

In [9]:
# Afficher tous les termes de la suite de Syracuse en partant de u0=19 jusqu'à obtenir un=1

u = 19
n = 0
while u != 1 :
    print(f"u({n})={u}")
    n += 1
    if u%2 == 0 :
        u = u//2
    else :
        u = 3*u + 1
print(f"Après le calcul de {n+1} termes on obtient u({n})={u}")
u(0)=19
u(1)=58
u(2)=29
u(3)=88
u(4)=44
u(5)=22
u(6)=11
u(7)=34
u(8)=17
u(9)=52
u(10)=26
u(11)=13
u(12)=40
u(13)=20
u(14)=10
u(15)=5
u(16)=16
u(17)=8
u(18)=4
u(19)=2
Après le calcul de 21 termes on obtient u(20)=1

Q10 - pour ceux qui sont plus à l'aise - Recopier et améliorer votre script pour qu'il affiche également la plus grande valeur atteinte par la suite (cela s'appelle la hauteur du vol).

In [10]:
# Déterminer la hauteur du vol de la suite de Syracuse partant de u0=19

u = 19
n = 0
hauteur = u

while u != 1 :
    print(f"u({n})={u}")
    n += 1
    if u%2 == 0 :
        u = u//2
    else :
        u = 3*u + 1
    if u>hauteur :
        hauteur = u
print(f"Après le calcul de {n+1} termes on obtient u({n})={u}")
print(f"La hauteur maximale atteinte est {hauteur}")
u(0)=19
u(1)=58
u(2)=29
u(3)=88
u(4)=44
u(5)=22
u(6)=11
u(7)=34
u(8)=17
u(9)=52
u(10)=26
u(11)=13
u(12)=40
u(13)=20
u(14)=10
u(15)=5
u(16)=16
u(17)=8
u(18)=4
u(19)=2
Après le calcul de 21 termes on obtient u(20)=1
La hauteur maximale atteinte est 88