ELECTIONS DÉPARTEMENTALES

Download Report

Transcript ELECTIONS DÉPARTEMENTALES

Lyc´ee Thiers
TP PYTHON - 11
S’amuser avec des rationnels ... est-ce bien raisonnable ?
1. Construction de la classe ratio
On se propose de construire une classe, dénommée “ratio” (pour rationnels ...). Conceptuellement,
l’idée est très simple : chaque instance de cette classe devra encapsuler deux informations, à savoir
le numérateur et le dénominateur d’une fraction d’entiers. Afin de garantir l’unicité de la représentation et de réduire au minimum la quantité de mémoire requise, les fractions en question devront
être irréductibles (numérateur et dénominateur premiers entre eux) et à dénominateur (strictement)
positif.
[Qu. 1] On rappelle que l’algorithme d’Euclide permet le calcul du PGCD de deux entiers a, b (a ∈ Z
et b ∈ N? ). Il consiste en une suite de divisions euclidiennes :
a = bq0 + r0
b = r0 q1 + r1
..
.
rn−2 = rn−1 qn + rn
|{z}
=0
La suite (rk ) est formée des restes successifs : elle décroît strictement jusqu’à ce qu’elle atteigne 0. Le
dernier reste non nul (noté rn−1 ci-dessus) est alors le PGCD de a et b.
Ecrire une fonction pgcd(a, b) qui renvoie le PGCD d’un couple d’entiers relatifs. On veillera à ce
que cette fonction s’applique à des arguments entiers de signes quelconques, en appliquant en fait
l’algorithme d’Euclide au couple (a, |b|) .
Une première mouture de la définition de la classe ratio pourrait être :
class ratio(object):
def __init__(self, p, q):
d = pgcd(p, q)
self.numer = p // d
self.denom = q // d
Trois principales objections à ce stade :
1) la division par d n’est pas sécurisée (on ne divise pas par 0 ...)
2) un entier est un rationnel particulier et l’on aimerait pouvoir passer un ou deux arguments au
constructeur ratio (soit le numérateur seul, auquel cas le dénominateur vaudrait implicitement
1, soit le numérateur et le dénominateur).
3) l’unicité de l’écriture n’est pas garantie : par exemple, le rationnel
p = 2, q = 3 mais aussi par p = −2, q = −3 .
2
3
est représenté par le couple
TP PYTHON - 11
2
[Qu. 2] Ecrire une seconde version de la définition de la méthode __init__, qui tienne compte des
remarques ci-dessus. En cas de difficulté, on pourra utiliser la solution proposée en annexe 1.
î A présent, on va procéder à la surcharge des opérateurs arithmétiques usuels et des opérateurs de
comparaison, de manière à ce qu’ils puissent s’appliquer à des instances de la classe ratio. Pour cela,
on enrichit la définition de la classe en y ajoutant des méthodes portant les noms imposés suivants :
__add__, __neg__, __sub__, __mul__, __truediv__ respectivement pour +, - (unaire et binaire), * et /
ainsi que :
__lt__, __le__, __gt__, __ge__, __eq__ respectivement pour < (less than), <= (less or equal), > (greater
than), >= (greater or equal) et == (equal)
Par exemple, on pourra définir :
def __mul__(self, other):
return ratio(self.numer * other.numer, self.denom * other.denom)
ou, mieux :
def _mul__(self, other):
if isinstance(other, ratio):
return ratio(self.numer * other.numer, self.denom * other.denom)
elif isinstance(other, int):
return ratio(self.numer * other, self.denom)
else:
return NotImplemented
[Qu. 3] En quoi cette seconde version est-elle meilleure que la première ? Compléter la définition de
la classe ratio, conformément aux consignes ci-dessus.
î Si l’on saisit dans la console :
>>> r = ratio(2, 3)
l’affichage de la valeur de r sera sans grand intérêt :
>>> r
<__main__.ratio object at 0x10198e210>
On a donc besoin de définir la méthode __repr__ pour obtenir un affichage plus “décent” :
>>> r
2 / 3
[Qu. 4] Ajouter la définition de la méthode __repr__. Ajouter également celle de la méthode
__float__ qui, appliquée à un rationnel (une instance de la classe ratio), doit renvoyer un float
représentant au mieux ce rationnel. On aura par exemple :
>>> r = ratio(1, 8)
>>> float(r)
0.125
[Qu. 5] Ajouter la définition de la méthode __radd__, qui permet de surcharger l’opérateur + de manière à traiter convenablement des expressions de la forme expr_de_type_int + expr_de_type_ratio.
Faire de même avec __rmul__, __rsub__ et __rtruediv__. On aura par exemple (et comportement analogue avec les autres opérations arithmétiques) :
TP PYTHON - 11
>>>
>>>
3 /
>>>
3 /
3
r = ratio(1, 2)
1 + r
2
r + 1
2
2. Repr´esentation d´ecimale
[Qu. 6] Ecrire une fonction devDec(r, n) qui renvoie, sous la forme d’une chaîne de caractères, les
n premiers chiffres décimaux du développement décimal du rationnel positif r, précédés de la partie
entière de n. Par exemple :
>>> devDec(ratio(480,7), 50)
’68.57142857142857142857142857142857142857142857142857’
ce qui est correct puisque :
480
4
= 68 + = 68 + 0, 571428....
7
7
Après s’être assuré du bon fonctionnement de devDec, l’insérer dans la définition de la classe ratio
sous la forme d’une méthode qu’on nommera dd (développement décimal). On aura alors :
>>> r = ratio(480,7)
>>> r.dd(12)
’68.571428571428’
h
i
[Qu. 7] A partir d’une liste de chiffres décimaux L = cp−1 , · · · , c0 , on souhaite construire le rationnel
dont le développement décimal est 0, cp−1 · · · c0 cp−1 · · · c0 ... (développement périodique illimité).
1) Exprimer ce rationnel comme le quotient de deux entiers (pas nécessairement premiers entre eux).
2) Ecrire la fonction demandée.
3) Quel est le rationnel dont le développement décimal est 0, 123123123123... ?
4) Quel est le rationnel dont le développement décimal est 2014, 1602123123123123... ?
3. Nombres harmoniques
1
1
(n > 1) .
+ ··· +
2
n
Ecrire une fonction harmonic(n) qui renvoie Hn (instance de la classe ratio). On aura par exemple :
[Qu. 8] Par définition, le n−ème nombre harmonique est Hn = 1 +
>>> harmonic(10)
7381 / 2520
[Qu. 9] On note Pn , Qn le numérateur et le dénominateur de Hn . Combien existe-t-il d’entiers n 6 2000
pour lesquels ...
1) Qn > Qn+1 ?
2) le chiffre des unités de Pn est un ’1’ ?
3) Hn est entier ?
On essaiera d’optimiser un peu, afin de ne pas calculer plusieurs fois la même chose !
[Qu. 10] On peut montrer (cf. annexe 2) que Hn n’est entier pour aucun n > 2. On
h peut
h h alors
h se
1
1
demander si les parties fractionnaires des Hn se répartissent “équitablement” entre 0, 2 et 2 , 1 ...
Rappelons que la partie fractionnaire d’un réel t est définie par θ (t) = t − btc ∈ [0, 1[ . Par exemple :
θ (π) ' 0, 14159.
TP PYTHON - 11
4
Pour tout n > 2, définissons :
pn =
1
1
card k ∈ {2, · · · , n} ; θ (Hk ) <
n−1
2
pn représente ainsi la proportion d’indices k ∈ {2, · · · , n} pour lesquels Hk se situe dans la moitié
gauche de l’intervalle limité par ses parties entières (par défaut et par excès).
Ecrire une fonction propLeftHalf(n) qui renvoie la liste p2 , · · · , pn . Cette fonction ne devra en
aucun cas faire intervenir d’expressions de type float.
Tracer (à l’aide de la fonction plot de matplotlib.pyplot) un graphique montrant l’évolution de la
proportion pn pour 2 6 n 6 3000. Cela devrait ressembler à :
4. Calcul approch´e d’une racine carr´ee
[Qu. 11] Dans la suite, ils sera utile de disposer d’une fonction qui calcule rn pour r rationnel et n
entier positif. Programmer cette fonction puis l’insérer dans la définition de la classe ratio, sous la
forme d’une méthode nommée __pow__ (ce qui aura pour effet de surcharger l’opérateur **).
[Qu. 12] Etant√donné des rationnels r > 0 et > 0, on peut calculer une valeur approchée rationnelle
et à près de r, en appliquant la méthode de dichotomie à la fonction t 7→ t2 − r sur le segment [1, r]
ou bien [r, 1] (selon que r > 1 ou r < 1). Rappeler brièvement le principe de cette méthode, expliquer
pourquoi elle se termine et pourquoi elle fournit bien le résultat√escompté. Ecrire alors une fonction
rcDichot(r, n) qui renvoie une approximation rationnelle de r à 10−n près par excès. On aura par
exemple :
>>> x = rcDichot(deux,10)
>>> x
759250125 / 536870912
>>> float(x)
1.4142135623842478
>>> from math import sqrt
>>> sqrt(2)
1.4142135623730951
Remarque. Un algorithme nettement plus performant est proposé à l’annexe 3.
TP PYTHON - 11
5
5. D´eveloppement en fraction continue
En appliquant l’algorithme d’Euclide à un couple d’entiers naturels non nuls (a, b) , et en notant
q0 , q1 , · · · , qn les quotients successifs, on constate que :
a
b
b
r0
1
b/r0
1
= q1 +
r0 /r1
..
.
= q0 +
rn−2
= qn
rn−1
En mettant bout à bout ces égalités, on obtient :
a
1
= q0 +
b
q1 + 1
.. 1
.+
qn
Cette écriture porte le nom de “développement en fraction continue” du rationnel positif a/b.
[Qu. 13] Ecrire une fonction decompFC(a, b) qui renvoie la liste q0 , · · · , qn .
[Qu. 14] Ecrire une fonction constructFromFC(L) qui, à partir d’une liste L = q0 , · · · , qn d’entiers
(avec q0 > 0 et qi > 1 pour tout i > 1), calcule et renvoie le rationnel correspondant.
[Qu. 15] On note Gn la liste de longueur n > 1 dont tous les termes valent 1.
1) Calculer et afficher, pour chaque n ∈ {1, · · · , 10} , le nombre rationnel représenté par Gn .
2) En utilisant le module matplotlib.pyplot, faire une figure montrant :
2.a) en noir, les points à coordonnées entières x, y vérifiant 0 6 x 6 14 et 0 6 y 6 22.
2.b) en rouge, ceux de coordonnées (Fk , Fk+1 ) où les Fk sont les nombres de Fibonacci et 0 6 k 6 7.
√
1+ 5
2.c) en bleu, la droite de pente g =
qui passe par l’origine.
2
3) Faire le lien entre les deux questions.
[Qu. 16] On note Vn = [1, 1, 2, 1, 1, 4, 1, 1, 6, · · · , 1, 1, 2n] ; il s’agit donc d’une liste de longueur 3n.
Ecrire une fonction approxV(n) qui renvoie le rationnel rn représenté par Vn . Afficher une valeur
approchée de r100 . Que peut-on conjecturer ? Contrôler avec le module sympy.
6. Fractions egyptiennes
[Qu. 17] Un peu de théorie pour commencer ...
n
X
1
où les qi sont des entiers
qi
i=1
naturels non nuls, tous distincts. Ce système était utilisé dans l’Egypte antique pour représenter des
quantités fractionnaires, comme en témoigne notamment le papyrus de Rhind, conservé au British
Museum.
On appelle “somme de fractions égyptiennes” tout expression du type
On peut montrer (et c’est l’objet de ce qui suit) que tout r ∈ Q ∩ ]0, 1[ peut être écrit sous cette forme.
Par exemple :
5
1
1
1
= +
+
17 4 23 1564
& '
q
?
On considère p, q ∈ N premiers entre eux, tels que p < q et l’on pose a =
.
p
TP PYTHON - 11
6
1) Justifier l’existence d’un entier r tel que 0 6 r 6 p − 1 et q = ap − r.
2) Que dire si r = 0 ?
3) On suppose r , 0. On peut alors écrire
p 1
r
= +
q a qa
p0
r
et recommencer le même processus : on écrit la fraction
sous forme irréductible 0 , puis on
qa
q
& 0'
p
pose a0 = 0 , ...
q
3.a) Prouver que le processus se termine (on vérifiera que p0 < p).
3.b) Prouver que a0 > 2a. Que peut-on en déduire concernant les dénominateurs des fractions
obtenues ?
[Qu. 18] Ecrire une fonction decompFE(u, v) qui, étant donnés deux naturels non nuls u et v, renvoie
la liste des dénominateurs des fractions produites par l’algorithme précédent. On aura ainsi :
>>> decompFE(5, 17)
[4, 23, 1564]
On fera en sorte de n’utiliser que des valeurs numériques de type int.
[Qu. 19] Ecrire une fonction sommeFE(L) qui, étant donnée une liste L = q1 , · · · , qn d’entiers naturels
n
X
1
. S’en servir pour vérifier, sur quelques exemples, la validité de la
non nuls, renvoie le rationnel
qi
i=1
fonction decompFE.
[Qu. 20] Trouver, parmi les rationnels de ]0, 1[ dont le dénominateur n’excède pas 20, celui (ou ceux)
donnant lieu à une décomposition avec un nombre maximal de termes.
[Qu. 21] Trouver, parmi les rationnels de ]0, 1[ dont le dénominateur n’excède pas 20, celui (ou ceux)
donnant lieu à une décomposition avec un dénominateur maximal.
2n
X
1
appartient à ]0, 1[ . Ecrire une
[Qu. 22] Vérifier que, pour tout n ∈
le rationnel An =
k
k=n+1
fonction decompFE_A(n) qui décompose An , avec l’algorithme précédent, en sommes de fractions
égyptiennes à dénominateurs tous distincts. Expérimenter pour 1 6 n 6 10. Que constate-t-on ?
N? ,
[Qu. 23] La suite de Sylvester est définie par :
a1 = 2 et ∀n ∈ N? , an+1 = 1 +
n
Y
ak
k=1
Ses premiers termes sont 2, 3, 7, 43, 1807, · · ·
1) Montrer que :
∀n ∈ N? , an+1 = a2n − an + 1
2) Montrer que :
1
1
1
+ ··· +
+
=1
a1
an−1 an − 1
3) Vérifier cette formule pour n = 10 à l’aide de la fonction sommeFE.
∀n > 2,
TP PYTHON - 11
7
Annexe 1 - version primitive de la d´efinition de la classe ratio
class ratio(object):
def __init__(self, p, q = 1):
if q == 0:
raise(ArithmeticError)
d = pgcd(p, q)
self.numer = p // d
self.denom = q // d
if q < 0:
self.numer = - self.numer
self.denom = - self.denom
Remarque. Cette définition est très incomplète ! Il manque les définitions de diverses méthodes comme
__add__, __mul__, __repr__, ...
Annexe 2 - pour n > 2, Hn =
n
X
1
k=1
k
n’est pas un entier
Etant donnés deux entiers naturels non nuls a, b et r = a/b, peut-on décider si r est entier ou non, en
connaissant seulement les parités de a et b .
Non ... sauf dans un cas : si a est impair et b est pair (auquel cas r n’est pas entier).
On va précisément montrer, par récurrence, que pour tout n > 2, Hn est le quotient d’un entier impair
par un entier pair.
1 3
C’est bien le cas de H2 = 1 + = . Supposons (HR) qu’on ait pour tout k ∈ {2, · · · , n} :
2 2
i
Hk = k
pk
avec ik , pk ∈ N? , ik impair et pk pair. Alors :
Hn+1 = Hn +
pn + (n + 1) in
1
=
(n + 1) pn
n+1
ce qui permet de conclure immédiatement si n + 1 est impair. Et dans le cas où n + 1 = 2k, on observe
que :
1
H2k = x + y
2
avec
1
1
x = 1 + + ··· +
3
2k − 1
de la forme a/i, avec i impair ; et
y = Hk
de la forme u/v avec u impair et v pair d’après HR. Ainsi :
a
u
2av + iu
H2k = +
=
i 2v
2iv
qui est bien le quotient d’un entier impair par un entier pair.
TP PYTHON - 11
8
√
Annexe 3 - Approximation rationnelle de
r par la m´ethode de Newton.
On considère un rationnel r > 1. En plus de la dichotomie
étudiée plus haut (section 3), une autre
√
méthode pour calculer une valeur approchée de r est celle de Newton-Raphson (alias “méthode de
la tangente”).
√
On considère un point du graphe de t 7→ t2 − r, d’abscisse a > r. La tangente en ce point coupe l’axe
des abscisses en un point d’abscisse a0 .
1) Faire une figure, puis exprimer a0 sous la forme a0 = F (a, r) où F est une fonction à préciser.
Observer que si a est rationnel, alors a0 aussi.
2) Ecrire une fonction rcNewtonStep(r, a) qui renvoie a0 (avec les notations précédentes). Bien
sûr : r, a, a0 sont des instances de la classe ratio.
√
√
√
3) Vérifier que a0 est une meilleure valeur approchée de r que a, c’est-à-dire que 0 6 a0 − r 6 a− r.
h√ √ i
4) On définit une suite (an )n∈N par a0 = s ∈
r, 2 r et ∀n ∈ N, an+1 = F (an , r) . Montrer que
√
lim an = r et que :
n→∞
√
∀n ∈ N, 0 6 an − r 6 2 (an − an+1 )
√
5) Ecrire une fonction rcNewton(r, n) qui renvoie une approximation rationnelle de r à 10−n près
par excès.
6) Comparer empiriquement les efficacités respectives de la méthode de dichotomie et de celle de
Newton.