Les équations de Pell-Fermat au bac S

Corrigé de l’exercice « spé » du bac S Métropole/Réunion 2017 et de quelques sujets de 2018
dimanche 8 juillet 2018
par  Alain BUSSER

Le sujet peut être trouvé ici. L’exercice portait sur les triangles rectangles presque isocèles (différence entre les côtés de l’angle droit égale à 1) à côtés entiers, comme le célèbre (3,4,5) ou le moins célèbre (20,21,29) :

On appelle « triangle rectangle presque isocèle », en abrégé TRPI, un triangle rectangle dont les côtés de l’angle droit ont pour longueurs x et x+1, et dont l’hypoténuse a pour longueur y, où x et y sont des entiers naturels.
Ainsi, un TRPI est un triangle rectangle dont les longueurs des côtés de l’angle droit sont deux nombres entiers consécutifs et dont la longueur de l’hypoténuse est un nombre entier.

Si le triangle de côtés x, x+1 et y, où y est la longueur de l’hypoténuse, est un TRPI, on dira que le couple (x ; y) définit un TRPI.

Partie A

1. Démontrer que le couple d’entiers naturels (x ; y) définit un TRPI si, et seulement si, on a : 2x²+2x+1=y²

Positionnement du problème

Si on nomme x, y et z les longueurs des côtés d’un triangle rectangle, le point de coordonnées (x,y,z) est situé sur un cône (représenté en bleu ci-dessous, x, y et z allant de -5 à 5) :

Un triplet pythagoricien est un point à coordonnées entières sur ce cône. Un TRPI correspond alors à un point sur ce cône, dont l’ordonnée est y=x+1 : Ceci est l’équation d’un plan (en rouge ci-dessous) qui coupe le cône selon une hyperbole :

Dans ce plan, l’équation de l’hyperbole est x²+(x+1)²=z² soit 2x²+2x+1=z². La réponse à la question 1 consistait donc à appliquer le théorème de Pythagore dans le TRPI.

On en arrive donc à chercher les points de coordonnées entières sur l’hyperbole d’équation 2x²+2x+1=y² :

Remarquer que les points tendent si vite vers l’infini que l’hyperbole est pratiquement confondue avec son asymptote. Ci-dessus on a interverti x et y pour caser plus de points sur la figure. L’exercice vise donc à résoudre une équation diophantienne.

2. Montrer que le TRPI ayant les plus petits côtés non nuls est défini par le couple (3 ; 5).

Corrigé

C’est justement de cette manière que Fermat résolvait les équations de Pell :

  1. déterminer (par essais successifs) la plus petite solution de l’équation diophantienne (ici (3 ;5) qui correspond au triangle 3-4-5) ;
  2. Trouver comment on peut passer de chaque solution à la suivante (à l’aide de matrices) et ainsi avoir un moyen algorithmique de décrire toutes les solutions.

On peut dire que cette méthode consiste à décrire les solutions de l’équation diophantienne par une équation paramétrique de l’hyperbole. La question 2 visait à trouver la plus petite solution. Ce script montre que la plus petite valeur de x non nulle qui convient est 3 :

On en déduit y=5.

3. a. Soit n un entier naturel. Montrer que si n² est impair alors n est impair.
b. Montrer que dans un couple d’entiers (x ;y) définissant un TRPI, le nombre y est nécessairement impair.

Corrigé

Pour le a, une démonstration par contraposition est simple, puisque la contraposée de ce qui est à démontrer est « si n est pair alors son carré aussi » :

  • Si n est pair alors il existe k tel que n=2k ;
  • Mais alors, n²=(2k)²=4k² est un multiple de 4.
  • A fortiori c’est un nombre pair.

Pour le b, on va utiliser le a, par exemple en réduisant modulo 2 l’expression 2x²+2x+1 qui, modulo 2, donne 0+0+1 : Le premier membre de l’équation est impair puisqu’il vaut 1 modulo 2. Mais il est égal à y² qui est impair aussi, et d’après le a il en est de même pour y lui-même.

4. Montrer que si le couple d’entiers naturels (x ;y) définit un TRPI, alors x et y sont premiers entre eux.

Corrigé

Si d est un diviseur commun à x et y alors, modulo d :

  • 2x² se réduit à 0 (car il est divisible par d) ;
  • 2x se réduit à 0 aussi
  • 1 se réduit à 1
  • donc 2x²+2x+1 est égal à 1, modulo d.

Mais puisque y² est divisible par d (par hypothèse), modulo d, l’équation 2x²+2x+1=y² se réduit à 0=1 ce qui montre par l’absurde que x et y n’ont pas de diviseur commun d : Ils sont premiers entre eux.

Partie B

On note A la matrice carrée, et B la matrice colonne ci-dessous :

À U=(x,y) on fait subir les transformations suivantes :

  • transposer U pour avoir un vecteur colonne ;
  • multiplier la matrice A par ce vecteur colonne ;
  • Additionner au résultat, le vecteur colonne B.

Le vecteur colonne résultant est, comme on va le voir ci-dessous, à nouveau une solution de l’équation diophantienne.

1. Exprimer x′ et y′ en fonction de x et y.
a. Montrer que : y′²−2x′(x′+1)=y²−2x(x+1).
b. En déduire que si le couple (x ;y) définit un TRPI, alors le couple (x′ ;y′) définit également un TRPI.

Corrigé

Avec le calcul matriciel on trouve

  • x’=3x+2y+1
  • y’=4x+3y+2

qui a été programmé en CaRScript pour le dessin sur hyperbole ci-dessus :

for([x,y]=[3,5];x<=2017;[x,y]=[3*x+2*y+1,4*x+3*y+2]){
	Println([x,y]);
}
Println([x,y]);

dont la version francisée [1] est

for([x,y]⟵[3,5];x≤2017;[x,y]⟵[3*x+2*y+1,4*x+3*y+2]){
	afficher([x,y]);
}
afficher([x,y]);

a. En remplaçant x’ par 3x+2y+1 et y’ par 4x+3y+2 dans l’expression y′²−2x′(x′+1) on trouve (4x+3y+2)²-2(3x+2y+1)(3x+2y+1+1), qui, après développement, donne y²-2x²-2x ; or en développant y²−2x(x+1) on a aussi y²-2x²-2x cqfd.

Remarque : Les compétences en calcul formel qui sont requises pour cette question ne vont pas au-delà du développement de produits de sommes de 3 termes. Pour autant, sur ce genre de questions, les élèves possesseurs d’une calculatrice « calcul formel » sont avantagés, et il est à se demander si la « spé maths » ne va pas, à terme, être réservée aux élèves ayant les moyens d’acquérir une telle calculatrice...

Le calcul formel est, ceci dit, à la portée de Sofus :

b. Du coup si le second membre est nul, il en est de même pour le premier : Si (x ;y) représente un TRPI, il en est de même pour (x’ ;y’).

2. Montrer par récurrence que, pour tout entier naturel n, le couple (xn ;yn) définit un TRPI.

Corrigé

  • Initialisation

Par hypothèse x0=3 et y0=5 et on a vu à la question 2 de la partie A que (3,5) représente un TRPI.

  • Hérédité

L’hypothèse de récurrence est que (xn,yn) représente un TRPI. Alors, d’après le 1.b, (xn+1,yn+1) aussi.

3. Déterminer, par la méthode de votre choix que vous préciserez, un TRPI dont les longueurs des côtés sont supérieures à 2017.

Corrigé

Les deux choix sont :

  • Calculer les termes successifs de la suite récurrente (ce qui a été fait avec CaRMetal) ;
  • Multiplier par A et ajouter B répétitivement ;

dans les deux cas, jusqu’à ce que x dépasse 2017.

On trouve, avec les matrices comme vu ci-dessous, ce début de liste :

[20, 29]
[119, 169]
[696, 985]
[4059, 5741]
[23660, 33461]
[137903, 195025]
[803760, 1136689]
[4684659, 6625109]
[27304196, 38613965]
[159140519, 225058681]

C’est le quatrième qui convient, et on peut vérifier que 4059²+4060²=32959081 et 5741²=32959081 aussi. Le triplet (4059 ; 4060 ; 5741) est donc pythagoricien.

Comme on a déterminé au début de l’exercice que les plus petites valeurs de (x,y) possibles sont (3,5), on itère l’affinité à partir de U=(3,5) :

Version itérateur

Comme chaque solution peut se calculer à partir de la précédente, on peut mettre en place un itérateur qui, à chaque fois qu’on lui applique la fonction next, donne la solution suivante. On peut dire que l’itérateur solutionCourante fournit, sur demande, la prochaine solution. Or Python3 permet de facilement créer un itérateur avec un générateur qui ressemble à une fonction :

def solutions(x=3,y=5):
    while y**2-2*x*(x+1)==1:
        x,y = 3*x+2*y+1,4*x+3*y+2
        yield x,y

solutionCourante = solutions()

for n in range(10):
    print(next(solutionCourante))

Comment améliorer l’énoncé ?

La transformation donnée dans l’exercice est affine, parce qu’il y a multiplication par une matrice et addition d’un vecteur constant. En changeant de repère, on peut annuler ce vecteur constant, et du coup non seulement l’algorithme est plus simple parce qu’il n’y a que la matrice, mais en plus la partie portant sur le calcul formel est considérablement plus simple, parce que chaque facteur n’a plus que 2 termes au lieu de 3.

On peut réécrire l’équation du sujet de bac ainsi :

  • 2x²+2x+1=y²
  • 4x²+4x+2=2y² (multiplication des deux membres par 2)
  • 4x²+4x+1+1=2y²
  • (2x+1)²+1=2y²
  • X²+1=2Y² (en notant X=2x+1 et Y=y)

L’équation définissant les TRPI peut maintenant s’écrire X²-2Y²=-1 : C’est une équation de Pell-Fermat. En fait, on est sur la même hyperbole mais son équation cartésienne a changé parce qu’elle n’est plus décrite dans le même repère. De plus, alors que l’ordonnée désigne toujours la longueur de l’hypoténuse, l’abscisse est la somme des côtés de l’angle droit, et pas le plus petit côté lui-même : Les côtés du TRPI sont (X-1)/2, (X+1)/2et Y. Par exemple, le triangle (20,21,29) est décrit dans le sujet de bac par le couple (20,29) et ici, par le couple (41,29).

On peut donc parcourir les 20 premiers triplets pythagoriciens désignant des TRPI par ce genre d’itérateur :

def trpi(x,y):
	assert(x**2-2*y**2==-1)
	for n in range(20):
		yield ((x-1)/2,(x+1)/2,y)
		x,y = 3*x+4*y,2*x+3*y

Avec cet affichage :

for t in trpi(7,5):
	print(t) 

on obtient ces triplets :

(119, 120, 169)
(696, 697, 985)
(4059, 4060, 5741)
(23660, 23661, 33461)
(137903, 137904, 195025)
(803760, 803761, 1136689)
(4684659, 4684660, 6625109)
(27304196, 27304197, 38613965)
(159140519, 159140520, 225058681)
(927538920, 927538921, 1311738121)
(5406093003L, 5406093004L, 7645370045L)
(31509019100L, 31509019101L, 44560482149L)
(183648021599L, 183648021600L, 259717522849L)
(1070379110496L, 1070379110497L, 1513744654945L)
(6238626641379L, 6238626641380L, 8822750406821L)
(36361380737780L, 36361380737781L, 51422757785981L)
(211929657785303L, 211929657785304L, 299713796309065L)
(1235216565974040L, 1235216565974041L, 1746860020068409L)

Dans ce nouveau repère,

  • x’=3x+2y+1 devient X’=2x’+1=2(3x+2y+1)+1=6x+4y+2+1=6x+3+4y=3(2x+1)+4y=3X+4Y
  • y’=4x+3y+2 devient Y’=y’=4x+2+3y=2(2x+1)+3y=2X+3Y

Et l’algorithme devient

Géométrie hyperbolique

On constate que la matrice M ci-dessus a un déterminant 1 : Elle peut donc être associée au demi-plan de Poincaré par la fonction z⟼(3z+4)/(2z+3). Or les matrices à coefficients entiers et de déterminant 1 sont engendrées par les deux matrices U et S ci-dessous :

La matrice S est d’ordre 2 parce que S²=-S ; et la matrice U est d’ordre 3. On note U’ l’inverse de U et S’ l’inverse de S. Le script ci-dessus montre que M=US’U’SU’S’US. Les puissances de M sont donc un sous-groupe du groupe des homographies du demi-plan de Poincaré.

Dans le demi-plan de Poincaré, l’infini est l’axe des abscisses. On peut donc voir « diverger rapidement » la suite des itérés de l’homographie dans le demi-plan de Poincaré. Ici, b=3 pour le sujet de bac et dans ce cas, la « convergence » se fait vers le nombre complexe √2 (qui est à l’infini puisque c’est un réel et que dans le demi-plan de Poincaré, les réels sont à l’infini !) :

Remarque sur cette figure : Le calcul sur les nombres complexes ne fonctionne pas dans la boucle, à cause de ce principe des expressions DGPad : Tout ce qui est avant le dernier point-virgule est du JavaScript ; seulement ce qui est après le dernier point-virgule est du DGPad.

Comme JavaScript ne reconnaît pas nativement les nombres complexes, il faut utiliser les fonctions de DGPad plus, times et quotient. Voici le source de la figure ci-dessus pour le vérifier (définition de l’expression E1 ; orbite est le nuage de points dans lequel on pousse au fur et à mesure les valeurs de z. Ici l’homographie itérée est (bz+b+1)/((b-1)z+b) qui est toujours de déterminant 1) :

// Coordinates System :
SetCoords(231.5,230,40,false,1001,579);


// Geometry :
P1=Point("P1",-3.8625,4.125);
b=Expression("b","b =","2","22","3","-5.5375","-1.5");
E1=Expression("E1","","","","var p=P1,orbite=[p];for(var n=1;n<=5;n++){p=quotient(plus(times(b,p),b+1),plus(times(b-1,p),b));orbite.push(p)};orbite","-4.7875","-3");
List1=List("List1",E1);


// Styles :
STL(P1,"c:#0000b2;s:6;f:30");
STL(b,"c:#007c7c;s:7;sn:true;f:24;p:2;i:1;cL:200;cPT:YzojMDA3YzdjO286MC41O3M6Ni41O2Y6MzA7aTox");
STL(E1,"c:#3d465f;h:1;s:7;f:24;p:2;cL:200;cPT:YzojNzgwMDEzO2g6MTtzOjEwO2Y6MzA=");
STL(List1,"c:#760012;s:0.8;f:30;p:0;sg:1");
SetCoordsStyle("isAxis:true;isGrid:true;isOx:true;isOy:true;isLockOx:false;isLockOy:false;centerZoom:false;onlyPositive:false;color:#111111;fontSize:18;axisWidth:1;gridWidth:0.1");
SetGeneralStyle("background-color:#F8F8F8;degree:true;dragmoveable:true");


// Texts :
Text("En rouge, l'orbite du point bleu \nsous l'it\u00e9ration de $\\frac{%b%z+%b+1%}{%b-1%z+%b%}$\nqui repr\u00e9sente la matrice $\\left( \\begin{array}{rr}%b% & %b+1% \\\\ %b-1% & %b% \\end{array}\\right)$\nde d\u00e9terminant 1: C'est une isom\u00e9trie \ndu demi-plan de Poincar\u00e9.",259,23,305,160,"c:rgba(59,79,115,0.18);s:3;r:15;p:4");

En bas de cet article, est évoquée une autre matrice de déterminant 1. Elle fait partie d’une autre famille de matrices, que voici :

Matrices encore plus simples

L’énoncé serait plus simple à ce stade là. Mais on peut encore simplifier, sinon l’énoncé, du moins les calculs, avec ce script testant une racine carrée d’une matrice carrée :

En effet il donne

[3, 4]
[2, 3]

Ceci suggère d’étudier, non les puissances de la matrice A de l’énoncé, mais celles de cette nouvelle matrice M, et de prendre une valeur sur deux seulement, comme étant sur l’hyperbole (l’autre valeur étant sur une autre hyperbole) :

L’hyperbole rouge a pour équation x²-2y²=-1 (c’est celle qui donne les TRPI), et l’hyperbole bleue a pour équation x²-2y²=1. On constate que les deux hyperboles ont les mêmes asymptotes et s’en rapprochent très vite. Mais avec un calcul similaire à celui du bac, on montre que si x’=x+2y et y’=x+y alors x’²-2y’²=-(x²-2y²). Ceci signifie que la multiplication par la matrice M transforme un point bleu en un point rouge et un point rouge en un point bleu.

Placer ces points dans un repère logarithmique peut se faire avec ce nouvel itérateur :

import matplotlib.pyplot as plt

def pell(x,y):
	for n in range(10):
		yield (x,y)
		x,y = x+2*y,x+y

plt.xscale('log')
plt.yscale('log')
		
for x,y in pell(1,1):
	if x**2-2*y**2>0:
		plt.plot([x],[y],'b^')
	else:
		plt.plot([x],[y],'rs')
	plt.annotate((x,y),xy=(x,y))
		
plt.show() 

Le dessin en coordonnées logarithmiques est plus lisible que celui avec les hyperboles :

On constate que si, dans l’exercice du bac, on divise l’ordonnée de U par son abscisse, les quotients successifs tendent rapidement vers √2 :

1.45
1.4201680672268908
1.4152298850574712
1.4143877802414389
1.4142434488588336
1.4142186899487321
1.4142144421220264
1.414213713314032
1.414213588270462
1.4142135668163807

Ce n’est pas étonnant : Si un triangle est presque isocèle, son hypoténuse vaut presque √2 fois le plus petit côté. C’est d’ailleurs en cherchant des approximations rationnelles de √2 qu’ont été découvertes les équations de Pell-Fermat. Les points bleus et les points rouges représentent des approximations différentes de √2, les rouges étant des TRPI, les bleus, non.

Voici donc un exercice assez voisin mais donnant lieu à des prolongements multiples :

Les ordonnées des vecteurs successifs forment une suite presque géométrique :

1
2
5
12
29
70
169
408
985
2378

Nombres de Pell

Ces nombres s’appellent nombres de Pell. Ils ressemblent à ceux de Fibonacci sauf qu’au lieu d’additionner les deux nombres précédents pour avoir le nombre courant, on additionne encore une fois supplémentaire l’avant-dernier terme de la suite. Autrement dit, alors que pour les nombres de Fibonacci

Fn+2=Fn+1+Fn,

pour les nombres de Pell :

Pn+2=2×Pn+1+Pn

Une suite géométrique vérifiant cette relation de récurrence doit avoir une raison r vérifiant r²=2r+1 (au lieu de r²=r+1 pour les suites de Lucas et Fibonacci) soit r=1-√2 (négative mais de valeur absolue inférieure à 1, donc vite négligeable) ou r=1+√2 : La « presque raison » de la suite de Pell est le nombre d’argent (alors que celle de la suite de Fibonacci est le nombre d’or).

On peut donc calculer les nombres de Pell par une relation matricielle de ce genre :

Cet itérateur convient également :

def pell(x=1,y=0):
    for n in range(20):
        x,y = 2*x+y,x
        yield y

print(list(pell()))

Il résulte de la définition par récurrence des nombres de Pell, que chaque nombre de Pell est « presque la moyenne géométrique » du précédent et du suivant, au sens où Pn-1×Pn+1-Pn²=(-1)n. Mais aussi, que

Quant aux abscisses des vecteurs précédents, on les appelle nombres de Pell-Lucas, et ils vérifient la même relation de récurrence mais avec une condition initiale différente. Ceux-ci sont assez faciles à calculer : Ce sont les moitiés des arrondis des puissances du nombre d’argent.

Entiers quadratiques

On peut partir d’une autre constatation, faite régulièrement au brevet des collèges : Si on considère des nombres de la forme a+b√2, après développement et simplification, on découvre que la somme de deux tels nombres est encore un nombre de la même sorte, et idem non seulement pour la différence, mais même pour le produit. On résume cela en disant que ces nombres forment un anneau, et il est possible de mener dans cet anneau des calculs similaires à ceux sur les entiers relatifs. En particulier on peut effectuer une division euclidienne...

Pour programmer cette structure d’anneau, on peut faire de la programmation objet avec Python 3 et sa reconnaissance de l’unicode :

class Entier2:
	def __init__(self,a=5,b=3):
		self.a = a
		self.b = b
	def __str__(self):
		return "{}+√̅2({})".format(self.a,self.b)
	def __add__(self,eq):
		return Entier2(self.a+eq.a,self.b+eq.b)
	def __sub__(self,eq):
		return Entier2(self.a-eq.a,self.b-eq.b)
	def __mul__(self,eq):
		return Entier2(self.a*eq.a+2*self.b*eq.b,self.a*eq.b+self.b*eq.a)
	def norme(self):
		return self.a**2-2*self.b**2
	def __pow__(self,n):
		p = Entier2(1,0)
		for k in range(n):
			p = p*self
		return p

Ces méthodes aux noms compliqués ont pour effet que les opérations se notent comme d’habitude en Python :

x = Entier2(1,1)
y = Entier2(3,2)
print(x+y)
print(x-y)
print(x*y)

Ce script

x = Entier2(1,1)
for n in range(10):
	print(x**n)

donne la suite d’entiers quadratiques suivants :

1+√̅2(0)
1+√̅2(1)
3+√̅2(2)
7+√̅2(5)
17+√̅2(12)
41+√̅2(29)
99+√̅2(70)
239+√̅2(169)
577+√̅2(408)
1393+√̅2(985)

ce qui montre que les couples de nombres vus ci-dessus forment une suite géométrique de raison 1+√2 et de premier terme 1. Et comme les TRPI sont la moitié de ces points, les TRPI forment une suite géométrique de premier terme 1+√2 et de raison 3+2√2.

Entiers quadratiques et équations de Pell

Mais les équations diophantiennes vues ci-dessus prennent une autre signification dans le contexte des entiers quadratiques : Si on appelle a-b√2 le conjugué de a+b√2, alors le produit d’un entier quadratique par son conjugué est un entier relatif, égal à a²-2b² et appelé norme de a+b√2. Les solutions des deux équations diophantiennes vues ci-dessus sont donc les entiers quadratiques de norme 1 ou -1 : On les appelles unités des entiers quadratiques. Comme la norme d’un produit est le produit des normes [2], la notion de nombres quadratiques premiers est plus compliquée que dans le cas des entiers relatifs : L’unicité de la décomposition en facteurs premiers n’est assurée qu’à une unité près, et ça fait pas mal de choix...

Le script python ci-dessous permet de dessiner les entiers quadratiques premiers (en rouge ; les unités sont en vert) :

import matplotlib.pyplot as plt

def diviseurs(n):
	t = [1]
	for d in range(2,n+1):
		if n%d==0:
			t.append(d)
	return t

def isPrime(n):
	return len(diviseurs(n))==2

for x in range(33):
	for y in range(25):
		N = abs(x**2-2*y**2)
		if isPrime(N):
			plt.plot([x],[y],'ro')
		else:
			if N==1:
				plt.plot([x],[y],'g^')
			else:
				plt.plot([x],[y],'b.')
		
plt.show() 

Les entiers quadratiques premiers sont assez nombreux, et il y a de surprenants alignements :

x²-3y²=1

Noter que c’est en résolvant de façon similaire l’équation diophantienne x²-3y²=1, qu’Édouard Lucas a trouvé le test de primalité de Lucas-Lehmer pour les nombres de Mersenne, encore utile de nos jours pour déterminer les plus grands nombres premiers connus. Les solutions de l’équation x²-3y²=1 se calculent ainsi :

ou avec cet itérateur :

def solutions(x=1,y=0):
    while x**2-3*y**2==1:
        x,y = 2*x+3*y,x+2*y
        yield x,y

solutionCourante = solutions()

for n in range(10):
    print(next(solutionCourante))

qui donne ces solutions (les 10 premières) :

(2, 1)
(7, 4)
(26, 15)
(97, 56)
(362, 209)
(1351, 780)
(5042, 2911)
(18817, 10864)
(70226, 40545)
(262087, 151316)

Voir aussi cet article sur une autre équation diophantienne : On y retrouve l’idée de parcourir les points à coordonnées entières sur une hyperbole, sur lesquels l’identité de Brahmagupta définit une structure de groupe. Une autre structure de groupe, avec du degré 3 cette fois-ci, est décrite ici.


Annexe : Pell-Fermat au bac 2018

Le sujet du Liban porte sur la suite de Fibonacci (en fait, une variante puisque la variable A est initialisée à 0 et non à 1). Pas de Pell-Fermat donc, mais on y voit le calcul de la suite de Fibonacci par les matrices :

Le sujet d’Asie par contre comportait l’équation x²-2y²=1 à la fois dans le sujet « obli » (résolution partielle de l’équation par un algorithme de balayage) et dans le sujet « spé », où les solutions s’obtiennent par calcul matriciel :

Version itérateur

Le générateur (qui engendre l’itérateur solutionCourante) s’appelle solutions puisqu’il va engendrer toutes les solutions, malgré le fait qu’il y en ait une infinité. Une fois qu’une solution a été affichée, on obtient la suivante avec la fonction next qui fait itérer l’itérateur :

def solutions(x=1,y=0):
    while x**2-2*y**2==1:
        x,y = 3*x+4*y,2*x+3*y
        yield x,y

solutionCourante = solutions(1,0)

for n in range(10):
    print(next(solutionCourante))

Le sujet Métropole-Réunion portait sur l’équation x²-8y²=1 ; il fallait prouver que l’équation a une infinité de solutions :

Version itérateur

Le générateur s’appelle solutions parce qu’il engendre les solutions (toutes les solutions, alors qu’il y en a une infinité). Mais l’itérateur s’appelle solutionCourante parce que, comme tout itérateur digne de ce nom, il ne donne qu’une solution à la fois :

def solutions(x=1,y=0):
    while 0==0:
        x,y = 3*x+8*y,x+3*y
        assert x**2-8*y**2==1
        yield x,y

solutionCourante = solutions(1,0)

for n in range(10):
    print(next(solutionCourante))

[1avec getZZ() qui se trouve dans la version 4.2 de CaRMetal

[2c’est l’identité de Brahmagupta, qui sert d’ailleurs à prouver les algorithmes de cet article.


Documents joints

SVG - 2.5 kio

Erreur d’exécution plugins/auto/sarkaspip/v4.1.0/noisettes/document/inc_images_jointes.html

Commentaires