Si certains exercices n'ont pas pu être terminés dans le cadre de cette séance, il est fortement conseillé de les terminer par vous-même chez vous ou en salle libre service.
Le but de ce TP est d'approfondir votre maîtrise des :
et de commencer à pratiquer les boucles « for
».
Pour ceci, nous utiliserons le débogueur intégré à Idle.
Un « débogueur » est un outil permettant de ... chercher des bogues dans un programme. Une fonctionnalité intéressante est la possibilité d'exécuter le programme pas à pas en regardant les valeurs des variables à chaque étape.
Pour activer le débogueur de Idle, il suffit de cocher D
ebugger
dans le menu D
ebug
de l'interpréteur. (Pour le désactiver, il faut décocher D
ebugger
...)
Une fois activé, le débogueur ouvrira une fenêtre supplémentaire ressemblant à celle ci :
Pour notre utilisation, il est préférable de décocher la case "Stack" et de cocher la case "Source".
Positionnez ensuite les trois fenêtre (fichier, interpréteur et débogueur) cote à cote, comme par exemple :
Lorsque que l'interpréteur évalue une expression, il procède pas à pas : il faut cliquer sur le bouton "Over" (ou "Step") du débogueur pour passer à la ligne suivante. D'autre part, la ligne que l'interpréteur s'apprête à exécuter est surlignée dans le fichier et la valeur des variables locales est affichée dans le débogueur. Par exemple, après quelques pas, on peut obtenir
Les boutons ont les significations suivantes :
Run Module
du menu R
un
), les définitions passent elles-même dans le débogueur. Il convient donc de cliquer sur le bouton "Go" pour évaluer tout le fichier et reprendre la main dans l'interpréteur.
On regarde la fonction compte_triangle
, qui utilise une boucle pour calculer la somme 1+2+3+...+n
:
def compte_triangle(n): """calcule le n-ème nombre triangulaire, en utilisant une boucle""" r = 0 for i in range(1, n+1): r = r+i return r
Activez le débogueur et évaluez l'expression compte_triangle(15)
. Vérifiez les choses suivantes :
range(...)
,
Utilisez le débogueur pour répondre aux questions suivantes :
for i in range(debut, fin, 1)
, est-ce que la variable i
prend la valeur fin
?
Nous utiliserons maintenant le code suivant, qui permet de compter combien de "6" ont étés obtenus lors de n
lancers d'un dé à 6 faces : (vous pouvez faire un copier/coller ou télécharger le fichier exemple-tp3.py contenant cette fonction et la suivante).
from random import randint def compte_6(n): """compte combien de "6" sont obtenus lors de n tirages aléatoires entre 1 et 6.""" compteur = 0 for i in range(0, n, 1): resultat = randint(1, 6) # tirage aléatoire d'un nombre entre 1 et 6 if resultat == "6": compteur = compteur + 1 return compteur
La première ligne nous permettra d'utiliser la fonction randint(a,b)
qui permet d'obtenir un nombre entier aléatoire entre a
et b
.
compte_6(600)
. Quel est le résultat attendu ? Quel est le résultat constaté ?
compte_6(600)
. Utilisez le mode pas à pas :
compte_6
,
6
et, lorsque vous avez trouvé l'erreur, appuyez sur la touche "Go" pour finir l'exécution.
Activez le débogueur et lancez l'évaluation de l'expression compte_6(35)
.
compte_6
,
randint
, le débogueur détaille le calcul de la fonction randint
, en ouvrant le code de cette fonction dans une nouvelle fenêtre,
randint
, il passe tout de suite à la ligne suivant l'appel en question, dans la fonction compte_6
, (vous pouvez alors refermer la fenêtre contenant le code de la fonction randint
)
randint
, le débogueur passe directement à la ligne suivante,
Écrivez une fonction fact
(pour factorielle) avec un argument entier n
pour calculer 1 * 2 * 3 * ... * n
.
Comme pour la fonction compte_triangle
, vous utiliserez un accumulateur pour calculer le résultat final par étapes successives.
Utilisez le débogueur pour vérifier la valeur de l'accumulateur à chaque tour de boucle. Pour n=5
, il doit valoir successivement
Mathématiquement, le nombre e est égal à la somme infinie 1 + 1/1! + 1/2! + 1/3! + 1/4! + ...
On peut donc calculer une approximation du nombre e en calculant 1 + 1/1! + 1/2! + 1/3! + 1/4! + ... + 1/n!.
approx_e
avec un argument entier n
pour calculer une telle approximation.
approx_e(100)
lorsque votre fonction fact
affiche des informations ? Commentez la ligne correspondante dans la fonction fact
avant de continuer.
approx_e
) pour afficher les approximations successives, et commentez cette ligne dès que vous avez répondu à la question suivante.
Mathématiquement, le nombre π/4 est égal à la somme infinie 1/1 + -1/3 + 1/5 + -1/7 + 1/9 + ...
On peut donc calculer une approximation du nombre π en calculant 4*(1/1 + -1/3 + 1/5 + -1/7 + ... + (-1)n/(2n+1)).
approx_pi
avec un argument entier n
pour calculer une telle approximation.
Lorsque l'on recherche des bogues, il est parfois utile d'arrêter une fonction à un endroit précis. Pour cela, on peut insérer des points d'arrêt dans le programme. Avec Idle, il suffit de faire un clique droit sur la ligne et de cliquer sur la commande Set Breakpoint
. La ligne sera alors surlignée en jaune.
Le bouton "Go" du débogueur permet de continuer l'exécution sans détails, jusqu'au point d'arrêt suivant.
On regardera maintenant le code suivant (vous pouvez faire un copier/coller ou télécharger le fichier exemple-tp3.py contenant cette fonction et la précédente)
from random import randint def compare_lancers(n): """compare les résultats obtenus en tirant 2n fois : - sur les n premiers tirages, en tirant un nombre entre 2 et 12, - sur les n tirages suivant, en tirant deux nombres indépendants entre 1 et 6 et en les additionnant. À chaque fois, les nombres sont ajoutés Le résultat sera la moyenne des tirages pour le type de tirage meilleur. Par exemple, on pourra obtenir (pour n=4) les tirages suivants - 7, 10, 2, 3 pour un total de 22, - 1+3, 2+2, 5+2, 6+4 pour un total de 25. La meilleure moyenne est donc 25/4 soit 6.25.""" resultat1 = 0 # total des tirages avec un nombre entre 2 et 12 for i in range(0, n, 1): nb = randint(2, 12) resultat1 = resultat1 + nb resultat2 = 0 # total des tirages avec deux nombres entre 1 et 6 for j in range(0, n, 1): nb1 = randint(1,6) nb2 = randint(1,6) resultat1 = resultat2 + nb1 + nb2 if resultat1 > resultat2: moyenne = resultat1 / n else: moyenne = resultat2 / n return moyenne
Désactivez le débogueur et évaluez l'expression compare_lancers(1000)
. Quel est le résultat attendu ? Quel est le résultat obtenu ?
Réactivez le débogueur et insérez un point d'arrêt sur la déclaration de resultat2
.
Lancez l'évaluation de compare_lancers(1000)
puis :
resultat1
.
i
et resultat
.
resultat2
. Lorsque que vous avez trouvé le bogue, terminez l'évaluation avec le bouton "Go".
Pourquoi est-il préférable de mettre le point d'arrêt sur la ligne précédent la boucle ? Refaites les mêmes opérations avec le point d'arrêt sur la ligne for j in range(1, n, 0)
.
Insérez un point d'arrêt sur la ligne contenant le return
et lancez l'évaluation de compare_lancers(1000)
. Arrêtez le débogueur sur la ligne contenant le return
et comparez les valeurs des variables resultat1
et resultat2
. Quel type de lancers est plus avantageux ?