09 Exos Fonctions Compléments Correction
Exercice 1⚓︎
-
Écrire une fonction
tableavec un argumentnqui produit l’affichage de la table den(de \(n\times 1\) à \(n\times 10\)) lorsqu'on l’appelle. Tester l’instructiontable(2)dans le Shell.🐍 Script Pythondef table(n): for nombre in range(1, 11): print(f"{nombre:2} * {n} = {nombre * n}") -
Modifier la fonction précédente de la manière suivante :
- elle prend maintenant 3 paramètres : n, debut, fin
- elle va afficher la table de
nde $n\times $début à $n\times $fin -
par défaut,
debutvaut 1 etfinvaut 10, mais on peut décider de les modifier lors de l'appel de la fonction.
Ainsi,table(9)va afficher la table de 9 entre \(9\times 1\) et \(9\times 10\) ;
maistable(9, 0, 12)va afficher la table de 9 entre \(9\times 0\) et \(9\times 12\) ;
🐍 Script Pythondef table(n, debut=1, fin=10): for nombre in range(debut, fin + 1): print(f"{nombre:2} * {n} = {nombre * n}") -
Comment appeler la fonction pour faire afficher la table de 7 entre \(7\times 1\) et \(7\times 12\) ?
🐍 Script Pythonoutable(7, 1, 12)🐍 Script Pythontable(n=7, fin=12)
Exercice 2⚓︎
-
Écrire une fonction (ou procédure)
repetequi répète le mot ’NSI’ un certain nombre de fois au choix, passé en paramètre.🐍 Script PythonAppel de la fonction :def repete(n): print(n * 'NSI')🐍 Script Pythonrepete(5) ### NSINSINSINSINSI -
Par défaut, le texte sera répété 2 fois.
Exercice 3⚓︎
Écrire une fonction qui prend en paramètres deux nombres x et y et renvoie le résultat de x² + y².
def dist_carree(x, y):
return x ** 2 + y ** 2
print(f"dist_carree(3, 4) = {dist_carree(3, 4)}")
### dist_carree(3, 4) = 25
Pour information, la représentation graphique de cette fonction de deux variables dans un repère orthonormé de l’espace (paraboloïde) :

Exercice 4⚓︎
-
Écrire une fonction
perimetre_triangle()qui prend en paramètres les 3 longueurs des côtés d’un triangle (en cm) et qui retourne son périmètre.🐍 Script Pythondef perimetre_triangle(a, b, c): p = a + b + c return p -
Écrire une fonction
est_constructiblequi renvoie s’il est possible de construire un triangle avec trois segments de mesures données. Cette fonction devra renvoyer un booléen.🐍 Script PythonCette fonction retourne un booléen que l'on peut utiliser directement dans un test :def est_constructible(a, b, c): if a > b + c or b > a + c or c > a + b: return False else: return True🐍 Script Pythona = 5 b = 6 c = 2 if est_constructible(a, b, c): print(f"Le triangle de côtés de longueurs {a}, {b}, {c} est constructible.") else: print(f"Le triangle de côtés de longueurs {a}, {b}, {c} n'est pas constructible.") ### Le triangle de côtés de longueurs 5, 6, 2 est constructible. a = 12 b = 4 c = 3 if est_constructible(a, b, c): print(f"Le triangle de côtés de longueurs {a}, {b}, {c} est constructible.") else: print(f"Le triangle de côtés de longueurs {a}, {b}, {c} n'est pas constructible.") ### Le triangle de côtés de longueurs 12, 4, 3 n'est pas constructible. -
Utiliser la fonction
inputet les deux fonctions précédentes pour écrire une fonctionsaisie_puis_perimetrequi demande à l'utilisateur la longueur de chaque côté d’un triangle (en cm) et, si celui-ci est bien constructible, retourne son périmètre.
def saisie_puis_perimetre():
a = float(input("Premier côté ? "))
b = float(input("Deuxième côté ? "))
c = float(input("Troisième côté ? "))
if est_constructible(a, b, c):
return perimetre_triangle(a, b, c)
Exercice 5⚓︎
Voici une fonction qui affiche à l'écran les paroles de la chanson "Babar" : https://comptines.tv/babar
def paroles_Babar():
print("""Babar dans la forêt
Partit se promener
Babar a rencontré
Un oiseau bleu qui faisait
Cui,Cui,Cui,Cui,Cui,Cui,
Cui,Cui,Cui,Cui,Cui,Cui,
Babar dans la forêt
Partit se promener
Babar a rencontré
Un canard gris qui faisait
Coin,Coin,Coin,Coin,Coin,Coin,
Coin,Coin,Coin,Coin,Coin,Coin,
Babar dans la forêt
Partit se promener
Babar a rencontré
Un corbeau noir qui faisait
Croa,Croa,Croa,Croa,Croa,Croa,
Croa,Croa,Croa,Croa,Croa,Croa,
Babar dans la forêt
Partit se promener
Babar a rencontré
Un grillon vert qui faisait
Cri,Cri,Cri,Cri,Cri,Cri,
Cri,Cri,Cri,Cri,Cri,Cri,
""")
paroles_Babar()
Solution :
Factoriser le code dans une fonction couplet, avec des paramètres bien choisis, de manière à ne pas répéter le code commun à tous les couplets. La chanson donnée a des couplets qui n'ont que peu de variations entre eux :
- l'animal rencontré
- le cri de cet animal
On peut donc factoriser tout le texte à afficher, en utilisant des variables pour l'animal et pour le cri.
def couplet(animal, cri):
print("""Babar dans la forêt
Partit se promener
Babar a rencontré
Un """ + animal
+" qui faisait\n"
+ 5 * (cri+",") + "\n"
+ 5 * (cri+","))
def paroles_Babar_factorise():
couplet("oiseau bleu", "Cui")
print()
couplet("canard gris", "Coin")
print()
couplet("coirbeau noir", "Croa")
print()
couplet("grillon vert", "Cri")
paroles_Babar_factorise()
Exercice 6⚓︎
Factoriser le code suivant :
from turtle import *
up()
goto(-300, 0)
#première maison
down()
forward(90)
left(90)
forward(60)
left(30)
forward(30)
left(120)
forward(30)
right(60)
forward(60)
left(90)
forward(60)
left(90)
up()
forward(120)
#deuxième maison
down()
forward(150)
left(90)
forward(100)
left(30)
forward(50)
left(120)
forward(50)
right(60)
forward(100)
left(90)
forward(100)
left(90)
up()
forward(200)
#troisième maison
down()
forward(210)
left(90)
forward(140)
left(30)
forward(70)
left(120)
forward(70)
right(60)
forward(140)
left(90)
forward(140)
left(90)
up()
forward(280)
done() ## pour la version sur Capytale
a = input() ## sur un autre éditeur, on peut aussi mettre un imput() pour éviter que la fenêtre ne se ferme...
Solution :
Le code donné dessine l'image suivante :

from turtle import *
# on définit une fonction qui dessine une maison avec un paramètre pour la taille
# et on exprime toutes les longueurs en fonction de ce paramètre
def maison(taille):
down()
forward(3 * taille)
left(90)
forward(2 * taille)
left(30)
forward(taille)
left(120)
forward(taille)
right(60)
forward(2 * taille)
left(90)
forward(2 * taille)
left(90)
up()
forward(4 * taille)
up()
goto(-200, 0)
# pour l'appel, on peut alors appeler 3 fois la fonction avec la taille appropriée :
#première maison
maison(30)
#deuxième maison
maison(50)
#troisième maison
maison(70)
# Ou alors on parvient à écrire une boucle et à exprimer la taille :
for i in range(3):
maison(30 + i * 20)
Exercice 7⚓︎
L'anniversaire de Théo tombe le 29 février. Il a rédigé un programme qui affiche s'il aura un 29 février cette année ou non.
Il l'a codé de la manière suivante :
def annee_chouette(a):
if a%400 == 0 or (a%4 == 0 and a%100 != 0) :
print("Chouette, cette année, j'ai un anniversaire !")
else:
print("Tant pis, encore pas cette année...")
Conformément aux "bonnes pratiques", créez une fonction bien nommée pour calculer le booléen correspondant au test du if.
Solution :
L'anniversaire de Théo tombe le 29 février. Il a rédigé un programme qui affiche s'il aura un 29 février cette année ou non.
Il l'a codé de la manière suivante :
def annee_chouette(a):
if a%400 == 0 or (a%4 == 0 and a%100 != 0) :
print("Chouette, cette année, j'ai un anniversaire !")
else:
print("Tant pis, encore pas cette année...")
Conformément aux "bonnes pratiques", créez une fonction bien nommée pour calculer le booléen correspondant au test du if.
L'idée est que la fonction annee_chouette(a) appelle, dans la condition du if, une fonction qui renvoie un booléen. Comme il s'agit de tester si l'année est bissextile ou non, c'est ainsi qu'on va l'appeler :
def annee_chouette(a):
if est_bissextile(a):
print("Chouette, cette année, j'ai un anniversaire !")
else:
print("Tant pis, encore pas cette année...")
Reste à définir cette fonction est_bissextile(a) :
soit on utilise directement la formule booléenne qui était donnée :
def est_bissextile(a):
return a%400 == 0 or (a%4 == 0 and a%100 != 0)
Soit, de manière plus détaillée, mais en fait un peu plus lisible, on peut régler les cas les uns après les autres, en profitant de la sortie de fonction par le return pour ne pas utiliser de else :
def est_bissextile_autre(a):
if a%4 != 0:
return False
if a%400 == 0:
return True
if a%100 == 0:
return False
return True
Exercice 8⚓︎
Le programme suivant est tout a fait optimisé, sans répétition dans l'écriture.
from turtle import *
def figure1():
for i in range(6):
down()
for j in range(10):
for k in range(6):
forward(50)
left(60)
left(36)
up()
left(60)
forward(120)
up()
goto(0, -100)
speed(10)
down()
figure1()
done() ## pour Capytale
Mais, d'une part, il contient des boucles dans des boucles, et d'autre part, il apparaît nettement qu'il est composé de petites parties auxquelles il est aisé de donner du sens (qui dessinent une figure plutôt simple).
Séparer ce code avec des plus petites fonctions bien nommées qui pourront être appelées dans la fonction figure1().
Solution :
Le programme donné dessine la figure suivante :

On constate qu'elle est constituée de 6 rosaces, chacune constituée de 10 hexagones.
On peut donc définir :
- une fonction
hexagone()qui contiendra la boucleforla plus intérieure ; - une fonction
rosace10hexagones()(ou un autre nom explicite) qui contient la boucleforintermédiaire ; - une fonction
figure1()qui ne contiendra qu'une seule bouclefor, et fera appel à la fonctionrosace10hexagones().
from turtle import *
def hexagone():
for i in range(6):
forward(50)
left(60)
def rosace10hexagones():
for i in range(10):
hexagone()
left(36)
def figure1():
for i in range(6):
down()
rosace10hexagones()
up()
left(60)
forward(120)
figure1()
On peut également rendre chacune de ces fonctions plus configurables, en passant des arguments en paramètres, par exemple la longueur du côté pour la fonction hexagone(cote), ou le nombre d'hexagones utilisés pour la fonction rosace(n)...
Ce serait très très bien. Mais ce n'était pas l'objet de cet exercice.
Ce qui est l'objet de cet exercice, en revanche, et auquel il faut apporter une attention particulière, c'est de bien nommer les fonctions (et les variables) pour qu'on comprenne immédiatement ce qu'elles sont censées faire.
Exercice 9 - pour les plus rapides⚓︎
- Ecrire une fonction qui prend en paramètres les 3 longueurs des côtés d’un triangle (en cm) et renvoie son aire en sortie.
Indication. Faire une recherche internet sur la formule de Héron.
On testera le programme à l’aide d’un triangle rectangle (dimensions de votre choix) dont l’aire est facile à calculer.
from math import sqrt
def aire_triangle_heron(a, b, c):
if not(est_constructible(a, b, c)): #on peut réutiliser la fonction de l'exo 1 pour faire cette vérification
print("Triangle non constructible")
return -1
p = (a + b + c) / 2
S = sqrt(p * (p - a) * (p - b) * (p - c))
return S
print(f"aire_triangle_heron(4, 5, 3) : {aire_triangle_heron(4, 5, 3)}")
### aire_triangle_heron(4, 5, 3) : 6.0
print(f"aire_triangle_heron(4, 5, 6) : {aire_triangle_heron(4, 5, 6)}")
### aire_triangle_heron(4, 5, 6) : 9.921567416492215
print(f"aire_triangle_heron(1, 5, 6) : {aire_triangle_heron(1, 5, 6)}")
### aire_triangle_heron(1, 5, 6) : 0.0
print(f"aire_triangle_heron(1, 5, 7) : {aire_triangle_heron(1, 5, 7)}")
### Triangle non constructible
### aire_triangle_heron(1, 5, 7) : -1
print(f"aire_triangle_heron(10000000000, 10000000000, 0.000000001) : {aire_triangle_heron(10000000000, 10000000000, 0.000000001)}")
### aire_triangle_heron(10000000000, 10000000000, 0.000000001) : 0.0
- (Source Wikipédia) La formule de Héron présente une instabilité lors du calcul numérique, qui se manifeste pour les triangles en épingle, c’est-à-dire dont un côté est de dimension très petite par rapport aux autres (confrontation de petites et grandes valeurs).
a. Tester avec des valeurs extrêmes (exemple : \(a = b = 1000000000\) et \(c = 0,000000001\)). Tests divers :
print(f"aire_triangle_heron(10000000000, 10000000000, 0.000000001) : {aire_triangle_heron(10000000000, 10000000000, 0.000000001)}")
### aire_triangle_heron(10000000000, 10000000000, 0.000000001) : 0.0
D'où vient le problème ?
Les entiers sont codés sur un nombre de bits qui dépend de leur taille. Les opérations sont exactes. On peut tester le calcul :
123456789123456789 + 1 - 123456789123456789
1, comme attendu.
En revanche, les flottants sont codés sur un nombre fixe de bits, de manière à coder leur ordre de grandeur (puissance de \(10\) correspondante, et un nombre fixe de chiffres significatifs. Lorsque le nombre comporte davantage de chiffres, les derniers sont perdus.
Lors d'opérations entre nombres flottants d'ordres de grandeur différents, cela peut vraiment poser problème.On peut tester le calcul :
123456789123456789.0 + 1.0 - 123456789123456789.0
0.0, ce qui est faux.
Il suffit de n'en garder que le début pour voir où est le problème :
123456789123456789.0 + 1.0
1.2345678912345678e+17, ce qui est une valeur arrondie, qui n'a pas gardé les unités.
b. En choisissant les noms de côtés de sorte à ce que \(a > b > c\), et en réorganisant les termes de façon à optimiser les grandeurs ajoutées ou soustraites, on obtient la formule de Kahan, plus stable :
\(A=\frac{1}{4}\sqrt{(a+(b+c))(c-(a-b))(c+(a-b))(a+(b-c))}.\)
Editer une nouvelle fonction utilisant cette formule de Kahan, puis tester les deux fonctions avec des valeurs extrêmes (exemple : \(a = b = 1000000000\) et \(c = 0,000000001\)).
def aire_triangle_kahan(a, b, c):
if not(constructible(a, b, c)): # on fait la vérification de la constructibilité
print("Triangle non constructible")
return -1
[a, b, c] = sorted([a, b, c]) # on peut remettre les valeurs dans l'ordre, au cas où elles ne le seraient pas
A = sqrt((c + (b + a)) * (a - (c - b)) * (a + (c - b)) * (c + (b - a))) / 4
return A
print(f"aire_triangle_kahan(4, 5, 3) : {aire_triangle_kahan(4, 5, 3)}")
### aire_triangle_kahan(4, 5, 3) : 6.0
print(f"aire_triangle_kahan(4, 5, 6) : {aire_triangle_kahan(4, 5, 6)}")
### aire_triangle_kahan(4, 5, 6) : 9.921567416492215
print(f"aire_triangle_kahan(1, 5, 6) : {aire_triangle_kahan(1, 5, 6)}")
### aire_triangle_kahan(1, 5, 6) : 0.0
print(f"aire_triangle_kahan(1, 5, 7) : {aire_triangle_kahan(1, 5, 7)}")
### Triangle non constructible
### aire_triangle_kahan(1, 5, 7) : -1
print(f"aire_triangle_kahan(10000000000, 10000000000, 0.000000001) : {aire_triangle_kahan(10000000000, 10000000000, 0.000000001)}")
### aire_triangle_kahan(10000000000, 10000000000, 0.000000001) : 5.0
print(f"aire_triangle_kahan(0.000000001, 10000000000, 10000000000) : {aire_triangle_kahan( 0.000000001, 10000000000, 10000000000)}")
### aire_triangle_kahan(0.000000001, 10000000000, 10000000000) : 5.0