Programme python pour calculer un investissement

Résolu/Fermé
jessaye14 - Modifié le 29 août 2022 à 14:45
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 - 1 sept. 2022 à 15:17

Bonjour,

Je cherche à créer un script python pour un investissement et je n'y arrive pas.

  • Je pars de 50€ je prends 8% des 50€, puis les additionnes à 50€ ce qui me donne 54€ (50 * 0.08 == 4).
  • Puis je rajoute 50€, et cette fois je prends les 8% de 104€ (104*0.08 = 8.32) et je les additionne à 104€ ce qui me donne 112.32
  • Et ainsi de suite... à l'infini en rajoutant à chaque fois 50€

3 réponses

mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
Modifié le 29 août 2022 à 14:59

Bonjour,

Il vaudrait mieux formuler ton problème comme une suite définie par récurrence ce serait plus clair. Et j'ai l'impression que tu t'es un peu emmêlé les pinceaux car si on rajoute 50€ à chaque fois on devrait avoir 162.32€ et non 112.32€. Voici à quoi ça ressemblerait :

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

u0 = 0
a = 1.08
b = 50

def f(n):
    return (
        u0 if n == 0 else
        a * f(n - 1) + b
    )

for n in range(10):
    print(f"{f(n):.2f}")

Ensuite, tu peux faire encore mieux en calculant la forme clause de ta suite définie par récurrence, voir ce lien :

Les suites récurrentes à 1 terme, ou d'ordre 1, de la forme u_n+1 = a * u_n + b où a, b et u_0 sont des nombres réels donnés, s'étudient très simplement :

Lorsque a est distinct de 1, il suffit d'étudier la suite auxiliaire définie par v_n = u_n - L où L désigne la limite éventuelle de (u_n), c'est à dire vérifiant  L = aL + b, soit L = b/(1 - a). La solution générale est alors donnée par :

u_n - L = a^n * (u_0 - L)

Dans ton cas (si j'ai bien compris) u0 = 0, a = 1.08 (on gagne 8%), b = 50 (on met 50€ à chaque tour de boucle) et donc L = 50 / (1 - 1.08).

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import math

u0 = 0
a = 1.08
b = 50
l = b / (1 - a)

def u(n):
    return math.pow(a, n) * (u0 - l) + l

for n in range(10):
    print(f"{u(n):.2f}")

Résultat :

0.00
50.00
104.00
162.32
225.31
293.33
366.80
446.14
531.83
624.38

Bonne chance

1
worox Messages postés 23 Date d'inscription mercredi 13 avril 2022 Statut Membre Dernière intervention 1 septembre 2022 9
Modifié le 30 août 2022 à 13:41

Sinon sans module, on peut écrire le code de cette manière ?

u = 0
a = 0.08
b = 50
for i in range(10):
    def jsp(x, y):
        global b
        pr = x / (1-y) + 50
        b = pr
        print(b)

    jsp(b, a)

Corrige moi si je me trompe.

Il peut aussi être marrant de visualiser graphiquement l'investissement. Je me suis amusé à donc le modéliser :

import matplotlib.pyplot as plt

nb = 0
nbl = []
xy = []
a = 0.08
b = 50

def jsp(x, y):
    global b
    global nb
    global nbl
    global xy
    pr = int(x / (1-y) + 50)
    b = pr
    nb += 1
    nbl.append(nb)
    xy.append(b)
    print(b)
for i in range(1000):
    jsp(b, a)

print(nbl)
print(xy)



plt.plot(nbl, xy)
plt.show()
plt.close()
1
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749 > worox Messages postés 23 Date d'inscription mercredi 13 avril 2022 Statut Membre Dernière intervention 1 septembre 2022
Modifié le 31 août 2022 à 10:47

Il y a des choses qui ne vont effectivement pas.

Dans le premier extrait de code :

  • Même si c'est syntaxiquement correct, il n'y a pas de raison de déclarer jsp dans la boucle for (la redéclaration est faite à chaque tour de boucle). Généralement, on déclare les fonctions plutôt en début de fichier, une fois pour toute.
  • On évite autant que possible les variables globales, comme c'est le cas pour b. C'est une mauvaise idée et en général ça n'est pas nécessaire. dans le cas présent, la fonction jsp devrait simplement retourner b, et du coup j'imagine l'appel devient b = jsp(n, a).
  • Ni a ni u ne sont utilisés, donc ça ne fait pas exactement la même chose que le code que je t'ai proposé. Par rapport à ton exercice, le fait que a ne soit pas utilisé montre que tu ne calcules pas ce qu'il faut.
  • Normalement on met des espaces autour des opérateurs (dont la soustraction) afin de se conformer à la norme PEP8.

Dans le second extrait de code, mes remarques additionnelles sont :

  • En terme de design, jsp n'a pas a remplir xy (ni nbl). C'est plutôt dans ta boucle for i qu'il faut construire ces deux vecteurs.
  • Vu que le comportement de u (cf mon message #1) est exponentiel, il est plus adéquat d'utiliser une échelle logarithmique sur l'axe des ordonnées.
  • Toute courbe devrait avoir :
    • Un titre
    • Un label sur l'axe des abscisses (et l'unité de la grandeur associée, si elle en a une)
    • Un label sur l'axe des ordonnées (et l'unité de la grandeur associée, si elle en a une)
  • Je recommande l'utilisation d'une grille pour améliorer la lisibilité
  • plt.close() n'est pas nécessaire.

Voici à quoi ça pourrait ressembler :

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import math
import matplotlib.pyplot as plt

u0 = 0
a = 1.08
b = 50
l = b / (1 - a)

def u(n):
    return math.pow(a, n) * (u0 - l) + l

n = 1000
x = [i for i in range(n)]
y = [u(i) for i in range(n)]

plt.xlabel("i")
plt.ylabel("log(u(i)) (€)")
plt.title("Progression de l'investissement")
plt.grid(True)
plt.semilogy(x, y)

Bonne chance

1
worox Messages postés 23 Date d'inscription mercredi 13 avril 2022 Statut Membre Dernière intervention 1 septembre 2022 9 > mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024
Modifié le 1 sept. 2022 à 14:35

merci beaucoup. Je ne vais pas te mentir, mon niveau en programmation n'est pas encore très élevé. Je n'ai pas l'habitude d'utiliser le module math ou numpy, ce qui doit être la cause des problèmes de mon programme. J'ai essayé de refaire ton programme sans code. 

Je n'ai rien à dire sur tes remarque très constructives que j'appliquerai dans mes projets. Et petit message, mais ça tu ne pouvais pas le savoir avant, je suis en seconde et je n'ai pas encore vu les logarithmes. C'est pour cela que je n'utilise pas ce procédé mathématique qui m'est encore pour l'heure inconnu.

Merci à toi. Et à bientôt sur le forum. 

2
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749 > worox Messages postés 23 Date d'inscription mercredi 13 avril 2022 Statut Membre Dernière intervention 1 septembre 2022
1 sept. 2022 à 14:36

Merci pour ton retour, je bascule le sujet en résolu. Bonne continuation et bon courage dans tes études !

0

Merci beaucoup pour votre aide, ça m'aide beaucoup!!

1
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
Modifié le 30 août 2022 à 12:36

Et du coup est-ce que ton problème est résolu ? Sinon que reste-t'il à voir ?

0
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 931
1 sept. 2022 à 15:00

Bonjour mamiemando

Il me semble que jessaye14 et worox sont 2 personnes différentes, du coup mettre le sujet résolu à la suite des messages de worox ne serait pas judicieux si j'ai raison,


D'autre part, je me permets une remarque.

Si j'ai bien compris la demande initiale, pour une période, on ajoute 50€ puis on perçoit 8% d'intérêt.

Donc pour la première période, on part de 0, auxquels on ajoute 50, on a donc 50, puis on augmente ce capital de 8%, soir 54€ à la fin de cette période.

Pour, la seconde période, on ajoute 50, on a donc 104, puis on augmente ce capital de 8%, soit 112,32€ à la fin de la période.

Je suis donc raccord avec la question initiale de jessaye14.

Mais tu lui as répondu 

si on rajoute 50€ à chaque fois on devrait avoir 162.32€ et non 112.32€. 

En début de 3eme période, ok, on bien 162,32, mais le but n'est il pas de connaître le total avec les intérêts générés sur la 3eme période, car si on se contente de montant en début de période, il y a 50 qui n'ont pas encore fait de petits.

Pour moi, le logiciel de devrait sortir un truc du style

"Période 1 investissement 50 €, capital 54€"
"Période 2 investissement 100 €, capital 112,32€"
"Période 3 investissement 150 €, capital 175,3056€"

0
Whismeril Messages postés 19029 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 26 avril 2024 931
Modifié le 1 sept. 2022 à 15:11

Ce qui, décomposé,donnerait ce code

capital = 0
investissementPeriodique = 50
taux = 1.08

for i in range(1,10):
    capital += investissementPeriodique
    capital *= taux
    print("Période", i, ": Investissement", i * investissementPeriodique, "€, capital", capital)

 Et cette sortie

Période 1 : Investissement 50 €, capital 54.0
Période 2 : Investissement 100 €, capital 112.32000000000001
Période 3 : Investissement 150 €, capital 175.3056
Période 4 : Investissement 200 €, capital 243.330048
Période 5 : Investissement 250 €, capital 316.79645184000003
Période 6 : Investissement 300 €, capital 396.1401679872001
Période 7 : Investissement 350 €, capital 481.8313814261761
Période 8 : Investissement 400 €, capital 574.3778919402703
Période 9 : Investissement 450 €, capital 674.328123295492
0
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
Modifié le 1 sept. 2022 à 15:18

Ah c'est possible, et j'avoue que quand j'ai répondu, j'avais des doutes sur mon interprétation. En tout cas si ton interprétation est la bonne, la démarche reste la même, il suffit simplement corriger la récurrence :

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

u0 = 0
a = 1.08
b = 50

def f(n):
    return (
        u0 if n == 0 else
        a * (f(n - 1) + b) # == a * f(n - 1) + a * b
    )

for n in range(10):
    print(f"{f(n):.2f}")

On voit que si à l'époque on ajoutait à chaque fois b maintenant on ajoute a * b. Pour la version itérative, il suffit de corriger b à 50 * 1.08:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
 
import math
import matplotlib.pyplot as plt
 
u0 = 0
a = 1.08
b = 50 * 1.08
l = b / (1 - a)
 
def u(n):
    return math.pow(a, n) * (u0 - l) + l
 
for n in range(10):
    print(f"{f(n):.2f}")

Concernant le fait que worox et jessaye14 sont deux personnes différentes, je ne sais pas, c'est possible. Vu la timeline, je pense que c'est simplement jessaye14 qui a créé un profil worox entretemps. Si ce sont deux personnes différentes, elles sont probablement dans la même classe (pour avoir le même exercice au même moment !) et j'imagine que si on répond à l'une, alors l'autre devrait aussi avoir sa réponse. Et si ça n'est pas le cas, rien n'empêchera cette éventuelle seconde personne de demander des précisions :-)

0