Vous êtes sur la page 1sur 10

ALG 07 Algorithme glouton

Fortement inspiré des cours de David Roche – pixees.fr

Lien DOCSHARE pour les algorithmes : link.dgpad.net/qm2m


Lien DOCSHARE pour les scripts en Python : link.dgpad.net/cuY5

I- Mais qu'est ce qu'un algorithme glouton ?


En informatique, un algorithme glouton (greedy algorithm en anglais) est un algorithme avec
plusieurs étapes et qui pour chaque étape fait un choix optimal (optimum local). Dans certains
cas cette approche permet d'arriver à la meilleure des solutions (une solution optimale ou optimum
global) mais ce n'est pas une obligation …

II- Le problème du sac à dos


1) Enoncé
Un cambrioleur (virtuel bien entendu !) possède un sac à dos ne pouvant pas supporter plus de 35 kg.
Lors de son cambriolage, il a la possibilité de dérober 4 objets A, B, C et D qui ont des masses et
des valeurs différentes (cf. tableau).
Déterminez les objets que le cambrioleur aura intérêt à dérober, sachant que :
 tous les objets devront tenir dans le sac à dos (35 Kg maxi)
 le cambrioleur cherche à obtenir un gain maximum. Objet A B C D
Masse 6 kg 11 kg 12 kg 8 kg
Valeur 220 € 385 € 300 € 320 €
Ce genre de problème est un problème d'optimisation.
Il existe souvent plusieurs solutions possibles à un problème mais pour un problème d'optimisation
on cherche la meilleur des solutions : la solution optimale (dans notre exemple on cherche le plus
grand gain possible). S'il existe plusieurs solutions optimales, il faut donc en trouver une…
A vous de trouver "à la main" la meilleure des solutions pour ce problème

Exo01*:
Trouver "à la main" la meilleure des solutions pour le problème ci-dessus.
Comparer vos solutions pour savoir si vous avez bien la meilleure des solutions et s'il en existe plusieurs.
2) Algorithme permettant de trouver la solution optimale
Il existe différentes méthodes algorithmiques permettant de trouver une solution optimale à un
problème d'optimisation : il peut, en effet, être intéressant "d'automatiser" la résolution des
problèmes d'optimisation à l'aide d'algorithme (dans notre cas, trouver un algorithme qui trouve
une solution optimale au problème du sac à dos).
En apparence, la solution la plus simple dans le cas du sac à dos serait d'écrire un algorithme qui
teste toutes les combinaisons d'objets possibles et qui retient les solutions qui offrent un gain
maximum. Dans notre cas précis, avec seulement 4 objets, cette solution pourrait être envisagée,
mais avec un plus grand nombre d'objets, le temps de calculs, même pour un ordinateur très
puissant, deviendrait trop important. En effet l'algorithme qui testerait toutes les combinaisons
possibles aurait une complexité en temps en O(a n) avec a une constante et n le nombre d'objets.
On parle d'une complexité exponentielle. Les algorithmes à complexité exponentielle ne sont pas
efficaces pour résoudre des problèmes, le temps de calcul devient beaucoup trop important quand
n devient très grand.
3) Algorithme glouton (ou méthode gloutonne) :
Nous avons une contrainte de masse avec un gain maximal à trouver.
a) Méthode gloutonne appliquée à des objets classés par C B D A
masse décroissante
12 kg 11 kg 8 kg 6 kg
À chaque étape, on sélectionne la masse la plus importante 300 € 385 € 320 € 220 €
possible et on calcule le gain.
1ère étape : C (12 kg) : il reste 35–12 = 23 kg et le gain est de 300 €
2ème étape : C (12 kg) : il reste 23–12 = 11 kg et le gain est de 300+300 = 600 €
3ème étape : B (11 kg) : il reste 11–11 = 0 kg et le gain est de 600+385 = 985 €
Résultat : le sac sera composé de 2 objets C et 1 objet B pour un gain de 985 €
Nous avons trouvé une solution mais est-elle optimale ? Correspond-t-elle à la solution
empirique trouvée "à la main"
B C D A
b) Méthode gloutonne appliquée à des objets classés par
11 kg 12 kg 8 kg 6 kg
valeur décroissante
385 € 300 € 320 € 220 €
A chaque étape, on sélectionne la valeur la plus importante
possible si la masse le permet et on calcule le gain.
1ère étape : B (11 kg) : il reste 35–11 = 24 kg et le gain est de 385 €
2ème étape : B (11 kg) : il reste 24–11 = 13 kg et le gain est de 385+385 = 770 €
3ème étape : B (11 kg) : il reste 13–11 = 2 kg et le gain est de 770+385 = 1155 €
Résultat : le sac sera composé de 3 objets B pour un gain de 1155 €
Nous avons trouvé une meilleure solution que précédemment mais est-elle optimale ?
c) Méthode gloutonne appliquée à des objets D A B C
classés par valeur massique décroissante (la 8 kg 6 kg 11 kg 12 kg
valeur massique est la valeur par kg)
320 € 220 € 385 € 300 €
A chaque étape, on sélectionne la valeur 320/8 = 220/6 = 385/11 = 300/12 =
massique la plus importante possible si la masse 40,0 €/kg 36,7 €/kg 35,0 €/kg 25,0 €/kg
le permet et on calcule le gain.
1ère étape : D (8 kg) : il reste 35–8 = 27 kg et le gain est de 320 €
2ème étape : D (8 kg) : il reste 27–8 = 19 kg et le gain est de 320+320 = 640 €
3ème étape : D (8 kg) : il reste 19–8 = 11 kg et le gain est de 640+320 = 960 €
4ème étape : D (8 kg) : il reste 11–8 = 3 kg et le gain est de 960+320 = 1280 €
Résultat : le sac sera composé de 4 objets D pour un gain de 1280 €
Nous avons trouvé une meilleure solution que les 2 précédentes. On pourrait penser qu'il s'agit
de la solution optimale … mais ce n'est pas vrai ! En effet, si je prends 3 objets D (3*8 = 24kg et
3*320 = 960 €) et un objet B : (1*11 = 11 kg et 1*385 = 385 €), j'obtiens bien 24+11 = 35 kg mais
la somme est de 960 + 385 = 1345 €……
La méthode gloutonne vue est toujours la même mais nous l'appliquons sur des objets classés
différemment et cet ordre de départ donne des résultats différents.
d) Conclusion
Plus généralement, il est important de bien comprendre qu'un algorithme glouton ne donne pas
forcement une solution optimale : il donne une solution approximative. Néanmoins, pour certains
types de problèmes, il est possible de montrer qu'un algorithme glouton donnera toujours une
solution optimale (la preuve dépasse largement le cadre de ce cours … et de mes compétences
mathématiques et informatiques !).
Exo02*
Écrire l'algorithme de la méthode gloutonne (c'est le même algorithme appliqué à 3 tableaux classés différemment) et
l'implémenter en PYTHON avec les valeurs données.
Écrire 3 fonctions différentes qui a en paramètre un tableau dont chaque élément est un tuple formé du
nom, de la masse et de la valeur de l'objet et qui renvoie un tableau rangé par :
 Masse décroissante
 Valeur décroissante
 Valeur massique décroissante
Exemple : tableau d'objets A, B, C et D : [(A, 9, 9), (B, 3, 4), (C, 5, 2), (D, 8,14)]
 Classé par masse décroissante : [(A, 9, 9), (D, 8,14), (C, 5, 2), (B, 3, 4)]
 Classé par valeur décroissante : [(D, 8,14), (A, 9, 9), (B, 3, 4), (C, 5, 2)]
 Classé par valeur massique décroissante : [(D, 8,14), (B, 3, 4), (A, 9, 9), (C, 5, 2)]
Trouver la meilleure solution pour un sac de 19 kg, pour un sac de 25 kg et pour un sac de 45 kg avec
objets A B C D E F G H I J K L M N
Masse (en kg) 6 3 5 8 7 4 20 6 2 4 4 10 2 10
Valeurs (en €) 9 3 8 14 10 7 20 7 3 3 6 12 2 4

II- Le problème du rendu de monnaie


1) Algorithme
L'algorithme consistant à rendre la monnaie avec un minimum de pièces (ou de billets) est un
algorithme glouton.
Il est nécessaire d'avoir un tableau récapitulant toutes les valeurs des pièces et des billets. A
vous de réfléchir dans quel ordre, il est obligatoire de classer ce tableau pour avoir le minimum de
pièces et de billets à rendre…

Exo03*
Écrire l'algorithme glouton du rendu de monnaie.
L'algorithme a au moins 2 variables : le prix à payer et la somme remise par le client.
Il doit avoir en sortie les billets et pièces à rendre afin qu'il y ait le moins possible de pièces et billets.
2) Fonction en Python

Exo04*
Implémentez votre algorithme dans une fonction permettant le rendu de monnaie.
La fonction doit calculer la somme à rendre à un client et indiquer les billets et pièces à rendre afin qu'il y ait le moins
possible de pièces et billets.
La fonction :
 a 2 paramètres en entrée :
 Un prix à payer (un ticket de caisse par exemple)
 Une somme d'argent liquide donné pour payer le prix
 renvoie 2 données :
 La somme d'argent à rendre au client
 Un tableau dont chaque élément est un tableau ou un tuple ou un dictionnaire contenant la valeur des
billets et pièces et le nombre de ces derniers à rendre.
Les pièces sont : 0,01 € ; 0,02 € ; 0,05 € ; 0,10 € ; 0,20 € ; 0,50 € ; 1 € ; 2 €
Les billets sont : 5 € ; 10 € ; 20 € ; 50 € ; 100 € ; 200 € ; 500 €
Exemple : prix à payer 11,24 € Argent donné 20 € Il faut donc rendre 20 – 11,24 = 8,76 €
Vous devez obtenir :
 3 pièces de 0,02 € + 1 pièce de 0,20 € + 1 pièce de 0,50 € + 1 pièce de 1 € + 1 pièce de 2€ + 1 billet de 5€
Vous ne devez pas obtenir :
 76 pièces de 0,01 € et 8 pièces de 1 € par exemple ………
Conseils :
 Attention aux variables locales et globales
 N'utiliser que des instructions simples (données dans l'aide-mémoire)
 Votre fonction doit vérifier si la somme donnée est bien supérieure au prix à payer
Corrigé ALG 07 Algorithme glouton
Exo02 problème du sac à dos
Mercredi 26/05, avec le groupe présent, nous avons établi l'algorithme suivant :
fonction gloutonne (tab, masseSac) :
# tab est un tableau classé dans l'ordre désiré contenant des tuples (nom, masse, valeur, valeur massique)
gain = 0 # variable correspondant au gain obtenu avec tous les objets "volés"
liste = [] # variable correspondant au tableau contenant tous les objets "volés"
i=0
tant que masseSac ≥ tab[–1][1] # tab[–1][1] désigne la valeur de la masse du dernier objet dans tab
si tab[i][1] ≤ masseSac
masseSac = masseSac – tab[i][1]
#on enlève la masse du sac de tab[i] à la masse restante du sac
gain = gain + tab[i][2] #on ajoute la valeur de tab[i] au gain obtenu
ajouter tab[i][0] à la variable liste
#on ajoute le nom de tab[i] au tableau contenant les noms des objets "volés"
sinon i = i + 1
renvoyer gain, liste, masseSac

Vous avez fait ensuite écrit la fonction en Python qui correspond :


def gloutonne(tab, masseSac) :
gain = 0
liste = []
i = 0
while masseSac >= tab[–1][1] :
if tab[i][1] <= masseSac :
masseSac = masseSac – tab[i][1]
gain = gain + tab[i][2]
liste.append(tab[i][0])
else :
i = i + 1
return gain, liste, masseSac

Cette fonction est testée avec les 3 cas vus dans le cours :
 Objets classés par masse décroissante :
gloutonne([("C",12,300),("B",11,385),("D",8,320),("A",6,220)],35)
renvoie (985, ['C', 'C', 'B'], 0)
Cela correspond à ce qui était prévu
 Objets classés par valeur décroissante :
gloutonne([("B",11,385),("C",12,300),("D",8,320),("A",6,220)],35)
renvoie (1155, ['B', 'B', 'B'], 2)
Cela correspond à ce qui était prévu
 Objets classés par valeur massique décroissante :
gloutonne([("D",8,320),("A",6,220),("B",11,385),("C",12,300)],35)
renvoie (960, ['D', 'D', 'D'], 11)
Cela ne correspond pas à ce qui était prévu : nous aurions dû trouver (1280, ['D', 'D', 'D',
'D'], 3)
À la fin de l'heure de mercredi, un de vos camarades (Maxime) a trouvé ce problème : l'algorithme n'est pas bon…
Le problème vient de la condition dans le "tant que" : mettre une condition sur la masse du dernier du tableau n'est
pas valable tout le temps. En effet, la masse la plus faible de tous les objets n'est pas forcément placée à la fin du
tableau ‼!

Il y a donc 2 possibilités :
 Soit avant la boucle, on cherche à déterminer la masse la plus faible de tous les objets mais cela nécessite de
faire une boucle passant en revue tous les objets de la liste (donc la durée d'exécution sera plus longue si le tableau est grand)
 Soit une change la condition : elle doit porter sur la masse du sac qui doit rester positive et sur le fait que le
nombre d'objets dans la liste ne doit pas être dépassé (ainsi la condition ne porte pas sur une valeur contenu
dans le tableau). J'ai proposé à Maxime la modification suivante du "tant que" :
tant que masseSac > 0 ET i < longueur du tableau
La fonction devient :
def gloutonne(tab, masseSac) :
gain = 0
liste = []
i = 0
while masseSac > 0 and i < len(tab) :
if tab[i][1] <= masseSac :
masseSac = masseSac – tab[i][1]
gain = gain + tab[i][2]
liste.append(tab[i][0])
else :
i = i + 1
return gain, liste, masseSac

Ainsi gloutonne([("D",8,320),("A",6,220),("B",11,385),("C",12,300)],35) renvoie


bien la bonne réponse (1280, ['D', 'D', 'D', 'D'], 3)

Je vous propose aussi une autre possibilité d'algorithme (et donc de fonction en Python) pour éviter de faire autant de
boucle avec quotient entier de la division ( // en Python) et le reste entier de la division (opérateur % en Python) :
fonction gloutonne (tab, masseSac) :
gain = 0
liste = []
i = 0
tant que masseSac > 0 ET i < longueur du tableau
nbObjets = quotient de la division (masseSac/masse de tab[i])
# on calcule commet de fois la masse de l'objet classé à la position i peut entrer dans la sac
masseSac = reste de la division (masseSac/tab[i][1])
#on calcule la masse restante du sac
gain = gain + nbObjets*tab[i][2] #on ajoute la valeur de tab[i] au gain obtenu
pour j allant de 0 à nbObjets
ajouter tab[i][0] à la variable liste
i = i+1
renvoyer gain, liste, masseSac

La fonction en Python devient :


def gloutonne (tab, masseSac) :
gain = 0
liste = []
i = 0
while masseSac > 0 and i < len(tab) :
nbObjets = masseSac // tab[i][1]
masseSac = masseSac % tab[i][1]
gain = gain + nbObjets * tab[i][2]
for j in range(nbObjets) :
liste.append(tab[i][0])
i = i + 1
return gain, liste, masseSac

Ensuite le problème à résoudre est de faire 3 algorithmes et donc 3 fonctions permettant de classer un tableau non
classé contenant des tuples (nom, masse, valeur) en
 Un tableau classé par masse décroissante (et en cas d'égalité des masses, par valeur de l'objet décroissante)
 Un tableau classé par valeur de l'objet décroissante (et en cas d'égalité des valeurs, par masse croissante)
 Un tableau classé par valeur massique décroissante (et en cas d'égalité, par masse croissante)

Pour cela je vous propose de reprendre l'algorithme de tri par insertion (ALG03) mais attention ce dernier avait
était établi pour un tri croissant sur un seul critère. Or nous avons ici des tris décroissants et sur 2 critères (le 2ème
critère est le classement en cas d'égalité sur le 1er critère) ….

L'algorithme du tri donné dans ALG03 pour trier dans le sens croissant
VARIABLE
t : tableau d'entiers i : nombre entier j : nombre entier k : nombre entier
DEBUT
j1
tant que j<longueur(t): //boucle 1
ij-1
kt[j]
tant que i≥0 et que t[i]>k: //boucle 2
t[i+1]t[i]
ii-1
fin tant que
t[i+1]k
jj+1
fin tant que
FIN
Adaptons-le pour créer une fonction en Python pour classer un tableau classé par masse décroissante (et en cas
d'égalité des masses, par valeur de l'objet décroissante) :
def classementMasse(tab):
for j in range(1,len(tab)):
i = j-1
k = tab[j] # k désigne un tuple ; k[1] désigne la masse de l'objet et k[2] désigne la valeur de
l'objet
while i>=0 and (tab[i][1] < k[1] or (tab[i][1] == k[1] and tab[i][2] < k[2]))
:
# tab[i][1] < k[1] permet le tri décroissant
# en cas d'égalité tab[i][1] == k[1], on trie par valeur de l'objet décroissante tab[i][2] < k[2]
tab[i+1] = tab[i]
i = i-1
tab[i+1] = k
return tab
Adaptons ce même algorithme pour créer une fonction en Python pour classer un tableau classé par valeur de
l'objet décroissante (et en cas d'égalité des valeurs, par valeur de masse croissante) :
def classementValeur(tab):
for j in range(1,len(tab)):
i = j-1
k = tab[j] # k désigne un tuple ; k[1] désigne la masse de l'objet et k[2] désigne la valeur de
l'objet
while i>=0 and (tab[i][2] < k[2] or (tab[i][2] == k[2] and tab[i][1] > k[1]))
:
# tab[i][2] < k[2] permet le tri décroissant
# en cas d'égalité tab[i][2] == k[2], on trie par masse de l'objet croissante tab[i][1] > k[1]
tab[i+1] = tab[i]
i = i-1
tab[i+1] = k
return tab
Adaptons ce même algorithme pour créer une fonction en Python pour classer un tableau classé par valeur
massique de l'objet décroissante (et en cas d'égalité des valeurs massiques, par valeur de masse croissante) :
def classementValeurMassique(tab): #Il faut d'abord créer une nouvelle donnée dans chaque tuple (la valeur
massique).
newtab=[] # création d'un nouveau tableau
for elt in tab : # boucle pour créer de nouveau tuple contenant une donnée de plus (la valeur massique)
valMas = elt[2]/elt[1] # nouvelle donnée : valeur massique = valeur/masse
elt =(elt[0], elt[1], elt[2], valMas)
# création du nouveau tuple avec 4 données (3 anciennes + valeur massique)
newtab.append(elt) # le nouveau tableau est rempli au fur et à mesure par les nouveaux tuples
for j in range(1,len(newtab)):
i = j-1
k = newtab[j] # k désigne un tuple ; k[3] désigne la valeur massique et k[1] la masse de l'objet
while i>=0 and (newtab[i][3]<k[3] or (newtab[i][3]==k[3] and newtab[i][1]>k[1])) :
newtab[i+1] = newtab[i]
i = i-1
newtab[i+1] = k
return newtab
Autre possibilité pour l'algorithme précédent (donné par Elouan):
def classementValeurMassique2(tab): #sans création d'une nouvelle donnée.
for j in range(1,len(tab)):
i = j-1
k = tab[j] # k désigne un tuple ; k[3] désigne la valeur massique et k[1] la masse de l'objet
while i>=0 and (tab[i][2]/tab[i][1] < k[2]/k[1]
or (tab[i][2]/tab[i][1] == k[2]/k[1] and tab[i][1] > k[1])) :
tab[i+1] = tab[i]
i = i-1
tab[i+1] = k
return tab
On va maintenant mettre en œuvre ces différentes fonctions pour le tableau donné dans l'énoncé :
[("A", 6, 9), ("B", 3, 3), ("C", 5, 8), ("D", 8, 14), ("E", 7, 10), ("F", 4, 7), ("G", 20, 20), ("H", 6, 7), ("I", 2, 3),
("J", 4, 3), ("K", 4, 6), ("L", 10,12), ("M", 2, 2), ("N", 10, 4)]
Pour différentes masses du sac : 19 kg, 25 kg et 45kg
J'ai créé 3 autres fonctions pour avoir les 3 résultats (classement par masse, par valeur et par valeur massique) en
même temps mais ce n'est pas du tout obligatoire :
def resultatTriparMasse(tab,masseSac) :
tabTriee=classementMasse(tab)
return gloutonne (tabTriee, masseSac)
def resultatTriparValeur(tab,masseSac) :
tabTriee=classementValeur(tab)
return gloutonne (tabTriee, masseSac)
def resultatTriparValeurMassique(tab,masseSac) :
tabTriee=classementValeurMassique(tab)
return gloutonne (tabTriee, masseSac)
et pour le script du programme principal qui consiste
 à déclarer le tableau et la masse du sac
 appeler les fonctions avec comme arguments les 2 variables précédentes
 afficher les résultats des 3 classements
data =[("A",6,9),("B",3,3),("C",5,8),("D",8,14),("E",7,10),("F",4,7),("G",20,20),("H",6,7),("I",2,3),
("J",4,3),("K",4,6),("L",10,2),("M",2,2),("N",10,4)]
masseMaxSac = 19
print("Résultat Algorithme Glouton avec masse du sac=",masseMaxSac,"kg")
print("tableau trié par masse décroissante: ",resultatTriparMasse(data,masseMaxSac))
print("tableau trié par valeur décroissante: ",resultatTriparValeur(data,masseMaxSac))
print("tableau trié par valeur massique décroissante:",resultatTriparValeurMassique(data,masseMaxSac))
Les résultats sont :
Résultat Algorithme Glouton avec masse du sac= 19 kg
tableau trié par masse décroissante: (26, ['L', 'D'], 1)
tableau trié par valeur décroissante: (31, ['D', 'D', 'I'], 1)
tableau trié par valeur massique décroissante: (31, ['F', 'F', 'F', 'F', 'I'], 1)
Résultat Algorithme Glouton avec masse du sac= 25 kg
tableau trié par masse décroissante: (28, ['G', 'C'], 0)
tableau trié par valeur décroissante: (28, ['G', 'C'], 0)
tableau trié par valeur massique décroissante: (42, ['F', 'F', 'F', 'F', 'F', 'F'], 1)
Résultat Algorithme Glouton avec masse du sac= 45 kg
tableau trié par masse décroissante: (48, ['G', 'G', 'C'], 0)
tableau trié par valeur décroissante: (48, ['G', 'G', 'C'], 0)
tableau trié par valeur massique décroissante: (77, ['F', 'F', 'F', 'F', 'F', 'F',
'F', 'F', 'F', 'F', 'F'], 1)
À chaque fois le critère de la valeur massique donne le meilleur résultat parmi les 3 proposés (avec une égalité)
mais nous n'avons pas la preuve qu'il s'agisse de la solution la plus optimale possible.

Exo03 algorithme problème du rendu de monnaie


Le problème est similaire au problème précédent, le même algorithme peut être utilisé. En effet, il consiste à rendre
la plus grande valeur possible à chaque tour (exemple : rendre 15,28 € se fait en rendant d'abord un billet de 10 #,
ensuite un billet de 5€ et ensuite une pièce de 0,20 €, 1 pièce de 0,02 € et une pièce de 0,01 €).
Nous allons donc avoir un tableau avec les valeurs des billets et pièces rangées dans le sens décroissant et nous
allons juste modifier le nom des variables pour le rendre plus compréhensible.
Exo02 Exo03
fonction gloutonne(tab, masseSac) : fonction gloutonne2(tab, monnaie) :
# tab est un tableau rangés suivant un critère contenant les objets sous forme de # tab est un tableau contenant les valeurs des billets et pièces classés
tuple (nom, masse, valeur) et masse Sac est la masse max du sac par ordre décroissant et monnaie la différence entre la somme donnée et la somme due
gain = 0
liste = [] # contient les objets pris liste = [] # contient la valeur des pièces et billets rendus
i = 0 i = 0
tant que masseSac>0 ET i<longueur(tab) tant que monnaie>0 ET i<longueur (tab)
si tab[i][1] ≤ masseSac si tab[i] ≤ monnaie
masseSac= masseSac – tab[i][1] monnaie = monnaie – tab[i]
gain = gain + tab[i][2]
ajouter tab[i][0] à la ajouter tab[i] à la variable liste
variable liste
sinon i = i + 1 sinon i = i + 1
renvoyer gain, liste, masseSac renvoyer liste, monnaie

Exo04 fonction problème du rendu de monnaie


Une fonction possible pour l'exo4 est :
def gloutonne2(tab, monnaie) :
liste = []
i = 0
while monnaie > 0 and i < len(tab) :
if tab[i] <= monnaie :
monnaie = monnaie – tab[i]
liste.append(tab[i])
else :
i = i + 1
return liste, monnaie

Si vous lancez gloutonne2([500,200,100,50,20,10,5,2,1,0.5,.2,.1,.05,.02,.01],2.54)


Le résultat est : ([2, 0.5, 0.02, 0.02], 3.469446951953614e-17)
NSI – Algorithme ALG
On constate qu'à la fin monnaie 0 . Le résultat est faible ( 3.5.10–17) mais non nul.
Cette différence provient du codage des nombres flottants (cf RD04). Cela pourrait paraitre anecdotique mais cela
provoque des erreurs.
Exemple : gloutonne2([500,200,100,50,20,10,5,2,1,0.5,.2,.1,.05,.02,.01],2.53) renvoie
([2, 0.5, 0.02], 0.009999999999999804) soit une erreur de 1 centime (la somme rendue est de
2,52 €  2.53 !)

Pour résoudre ce problème, il est nécessaire


 soit de travailler avec des entiers. En effet, nos valeurs sont des flottants avec au plus 2 chiffres après la
virgule : si nous travaillons avec des centimes (la valeur en € *100), nous sommes certains de travailler
avec des entiers.
def gloutonne2(tab, monnaie) :
# ATTENTION, tab contient les valeurs classées des billets et pièces mais en centimes d'euros
et monnaie est en centimes d'euros
liste = []
i = 0
while monnaieCentimes > 0 and i < len(tab) :
if tab[i] <= monnaieCentimes :
monnaie = monnaie – tab[i]
liste.append(tab[i]/100) #/100 pour avoir la valeur des pièces et billets en €
else :
i = i + 1
return liste, monnaie
 Soit de travailler avec des valeurs arrondis à 2 chiffres décimaux en utilisant round(nb,2)
La fonction devient :
def gloutonne2(tab, monnaie) :
# ATTENTION, tab contient les valeurs classées des billets et pièces mais en €
et monnaie est en €
liste = []
i = 0
while monnaie > 0 and i < len(tab) :
if round(tab[i],2) <= round(monnaie,2) :
monnaie = round(monnaie,2) – round(tab[i],2)
liste.append(tab[i])
else :
i = i + 1
return liste, monnaie
Néanmoins, si on respecte l'énoncé, la fonction doit avoir 2 paramètres : un prix à payer, une somme d'argent à
renvoyer la somme à rendre, un tableau comportant des tuples (valeur billets ou pièces et nombre de ces billets ou
pièces), il faut apporter quelques modifications. Il est beaucoup plus pratique de reprendre l'algorithme vu à
l'Exo02 permettant de calculer le nombre de pièces ou billets pris à chaque fois (avec % et //)
def gloutonne3(facture, argent) :
tab= [500, 200, 100, 50, 20, 10, 5, 2, 1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01]
if argent>=facture :
monnaie = argent–facture
liste = []
i = 0
while monnaie > 0 and i < len(tab) :
nb = round(monnaie,2) // round(tab[i],2)
monnaie = round(monnaie,2) % round(tab[i],2)
if nb !=0 :
liste.append((tab[i],nb))
i = i + 1
return argent–facture, liste
else :
return "facture > argent donné"

Vous aimerez peut-être aussi