Listes et suites numériques
Cours complet · algorithmique et programmation (première), chapitre 3 · première, algorithmique et programmation
Travailler ce chapitre sur Adloun
Une suite numérique est une liste infinie ; une liste Python en capture les premiers termes. Ce chapitre met les listes au service du chapitre « Suites » du manuel de mathématiques : générer les termes, les représenter, les sommer, conjecturer la nature ou la limite d'une suite.
3.1 La liste des termes d'une suite
Les deux modes de définition d'une suite correspondent exactement à deux modes de génération de listes :
# Suite EXPLICITE u_n = f(n) : une compréhension suffit
U = [n**2 / (n + 1) for n in range(20)]
# Suite RÉCURRENTE u_{n+1} = f(u_n) : ajouts successifs obligatoires
# (chaque terme dépend du précédent)
V = [5] # premier terme
for i in range(19):
V.append(0.8 * V[-1] + 4) # V[-1] : le dernier terme calculé
Pour une suite récurrente, V[-1] (le dernier élément) joue le rôle de dans la relation : la liste mémorise tout l'historique, là où le chapitre 1 ne gardait que le terme courant dans une variable. Disposer de la liste complète permet ensuite d'observer, tracer, sommer.
Méthode : Fonction renvoyant la liste des termes
Encapsuler la génération dans une fonction paramétrée par le nombre de termes :
def termes(n):
# Les n premiers termes de u_{k+1} = 0.8 u_k + 4, u_0 = 5
L = [5]
for i in range(n - 1):
L.append(0.8 * L[-1] + 4)
return L
print(termes(6)) # [5, 8.0, 10.4, 12.32, 13.856, 15.0848]
3.2 Représenter graphiquement une suite
Une suite se représente par les points isolés — jamais reliés :
import matplotlib.pyplot as plt
U = termes(25)
plt.plot(range(len(U)), U, "o") # "o" : points non reliés
plt.xlabel("n")
plt.ylabel("u_n")
plt.grid()
plt.show()
Le graphique suggère que les termes montent vers : une conjecture de limite, à vérifier par le calcul du point fixe , soit .
Le nuage produit par le programme : les termes de s'accumulent sous la droite (pointillé) — la limite conjecturée.
3.3 Sommes de termes
# 1. Accumulateur (chapitre 1)
S = 0
for k in range(1, 101):
S = S + k
# 2. sum() sur une liste en compréhension
S = sum([k for k in range(1, 101)])
# 3. Formule du cours (à privilégier quand elle existe !)
S = 100 * 101 // 2
# Les trois donnent 5050. Vérification croisée d'une DÉMONSTRATION
# par un CALCUL : c'est une bonne habitude scientifique.
q, n = 3, 10
par_somme = sum([q**k for k in range(n + 1)])
par_formule = (1 - q**(n + 1)) / (1 - q)
print(par_somme, par_formule) # 88573 88573.0 : la formule est confirmée
3.4 Conjecturer la nature d'une suite
Méthode : Listes des différences et des quotients
Une liste de termes étant donnée, on fabrique par compréhension :
- la liste des différences : si elle est constante, la suite est (probablement) arithmétique de raison cette constante ;
- la liste des quotients (termes non nuls) : si elle est constante, la suite est (probablement) géométrique.
def differences(L):
return [L[i+1] - L[i] for i in range(len(L) - 1)]
def quotients(L):
return [L[i+1] / L[i] for i in range(len(L) - 1)]
A = [3, 7, 11, 15, 19]
print(differences(A)) # [4, 4, 4, 4] -> arithmétique de raison 4
G = [2, 6, 18, 54, 162]
print(quotients(G)) # [3.0, 3.0, 3.0, 3.0] -> géométrique de raison 3
V = termes(8)
print(differences(V)) # [3.0, 2.4, 1.92, ...] : ni constante...
print(quotients(differences(V))) # [0.8, 0.8, ...] : mais les écarts
# forment une suite géométrique !
La machine conjecture, le cours démontre : les rôles sont complémentaires. (Pour , la suite auxiliaire est géométrique de raison — l'exercice type du chapitre Suites.)
3.5 Seuils et limites
Chercher un seuil, c'est avancer dans la suite jusqu'à franchir une barre dont on ignore à quel rang elle sera atteinte :
Méthode : Algorithme de seuil, version liste
Chercher le premier rang où la suite franchit un seuil, en renvoyant aussi la liste des termes calculés (pour contrôle ou tracé) :
def seuil(objectif):
# Premier n tel que u_n > objectif, pour u_{n+1} = 1.05 u_n, u_0 = 1000
L = [1000]
while L[-1] <= objectif:
L.append(1.05 * L[-1])
return len(L) - 1, L # le rang ET l'historique
rang, historique = seuil(2000)
print(rang) # 15 : à 5 % par an, doubler prend 15 ans
Pour la suite du chapitre Exponentielle :
U = [(1 + 1/n)**n for n in range(1, 10**6, 10**5)]
# [2.0, 2.7182681..., 2.7182750..., ...] -> stabilisation vers e = 2.71828...
La liste rend la convergence visible ; l'écart à décroît lentement (en environ), ce que la liste des écarts [abs(x - 2.718281828) for x in U] confirme.
3.6 Deux suites célèbres en listes
def fibonacci(n):
F = [1, 1]
for i in range(n - 2):
F.append(F[-1] + F[-2])
return F
F = fibonacci(20)
print(quotients(F)[-5:])
# [1.6180338..., 1.6180340..., 1.6180339..., ...] : les quotients de termes
# consécutifs se stabilisent vers le NOMBRE D'OR (1 + rac(5))/2 = 1.6180339...
La liste des quotients transforme une curiosité en conjecture précise — démontrable en terminale.
Pour la suite de Syracuse (diviser par si pair, sinon tripler et ajouter ), on appelle temps de vol le nombre d'étapes pour atteindre :
def vol(u0):
# Liste complète de la trajectoire depuis u0 jusqu'à 1
L = [u0]
while L[-1] != 1:
if L[-1] % 2 == 0:
L.append(L[-1] // 2)
else:
L.append(3 * L[-1] + 1)
return L
print(vol(7)) # [7, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1]
print(len(vol(7)) - 1) # temps de vol : 16
print(max(vol(27)), len(vol(27)) - 1) # altitude max 9232, temps de vol 111 !
Depuis , la trajectoire culmine à avant de retomber : les listes révèlent ces comportements imprévisibles — la conjecture de Syracuse (tout finit à ) résiste depuis 1937.
La trajectoire de Syracuse depuis : des rebonds imprévisibles (maximum ), puis la chute vers le cycle final .
3.7 Exercices d'entraînement
Difficulté : ★ facile ★ moyen ★ plus difficile.
Exercice
Générer la liste des premiers termes de : (a) (compréhension) ; (b) et (ajouts successifs).
Solution
U = [3*n - 1 for n in range(12)] # [-1, 2, 5, ..., 32]
V = [2]
for i in range(11):
V.append(3 * V[-1] - 4) # [2, 2, 2, ...] surprise : suite
# constante (2 est point fixe !)
(b) réserve une surprise : , la suite est constante — est solution de .
Exercice
À l'aide de differences et quotients, conjecturer la nature de la suite dont voici les premiers termes : [400, 380, 361, 342.95]. S'agit-il d'une suite arithmétique ? géométrique ?
Solution
differences donne [-20, -19, -18.05] : non constante, pas arithmétique. quotients donne [0.95, 0.95, 0.95] : géométrique de raison (une baisse de par étape).
Exercice
Écrire une fonction sommes_partielles(L) renvoyant la liste des sommes . Vérifier sur [1, 2, 3, 4, 5], puis utiliser cette fonction pour retrouver que les sommes partielles de [1, 3, 5, 7, 9, 11] (impairs) sont des carrés parfaits.
Solution
def sommes_partielles(L):
S = []
total = 0
for x in L:
total += x
S.append(total)
return S
print(sommes_partielles([1, 2, 3, 4, 5])) # [1, 3, 6, 10, 15]
print(sommes_partielles([1, 3, 5, 7, 9, 11])) # [1, 4, 9, 16, 25, 36]
Les sommes des premiers impairs sont : les carrés — conjecture , démontrable avec la somme arithmétique du cours.
Exercice
Un capital de € est placé à par an.
- Générer la liste des soldes sur ans et tracer le nuage de points (code matplotlib).
- Par un algorithme de seuil, déterminer en combien d'années le capital dépasse €.
Solution
C = [3000]
for i in range(20):
C.append(C[-1] * 1.025)
import matplotlib.pyplot as plt
plt.plot(range(len(C)), C, "o")
plt.show()
n, c = 0, 3000
while c <= 4000:
c = c * 1.025
n += 1
print(n) # 12 : le cap des 4000 euros est franchi la 12e année
Exercice
La suite , est celle de Héron pour .
- Générer la liste de ses premiers termes.
- Construire la liste des écarts et commenter la vitesse de convergence.
Solution
U = [1]
for i in range(5):
U.append((U[-1] + 7 / U[-1]) / 2)
# [1, 4.0, 2.875, 2.6548..., 2.64577..., 2.6457513...]
ecarts = [abs(x - 7**0.5) for x in U]
# [1.65, 1.35, 0.229, 0.0090, 1.5e-05, 4.4e-11]
Le nombre de décimales exactes double à chaque étape (convergence dite quadratique) : cinq itérations donnent déjà dix décimales de .
Exercice
Écrire une fonction temps_de_vol(u0) renvoyant seulement le temps de vol de Syracuse, puis construire la liste des temps de vol pour de à . Quel départ donne le vol le plus long ?
Solution
def temps_de_vol(u0):
n, u = 0, u0
while u != 1:
u = u // 2 if u % 2 == 0 else 3*u + 1
n += 1
return n
vols = [temps_de_vol(u0) for u0 in range(1, 101)]
record = max(vols)
depart = vols.index(record) + 1 # +1 : indice 0 correspond à u0 = 1
print(depart, record) # 97 118 : depuis 97, 118 étapes !
Le champion sous est avec étapes — introuvable sans machine.
Exercice
On considère la suite définie par et (suite logistique).
- Générer ses premiers termes. La suite semble-t-elle converger ?
- Reprendre avec . Comparer les deux listes au rang : que constate-t-on ?
Solution
def logistique(u0, n):
L = [u0]
for i in range(n - 1):
L.append(4 * L[-1] * (1 - L[-1]))
return L
A = logistique(0.2, 20)
B = logistique(0.2000001, 20)
print(A[19], B[19]) # par exemple 0.5800... et 0.9863... : très différents !
1. Les termes sautent dans sans jamais se stabiliser : pas de limite apparente.
2. Une perturbation de sur donne des trajectoires complètement différentes au bout de étapes : c'est la sensibilité aux conditions initiales, signature du chaos — et la raison pour laquelle la météo à long terme est imprévisible.