Feuille d’exercices 6#

Objectifs

  • Nombres réels

  • Notion de précision

  • Affichage graphique

Exercice 1. Manipulation de nombre flottant avec une précision donnée#

Question 1 : Effectuer successivement les instructions suivantes.

  1. Stocker dans une variable x le rationnel \(1/7\).

  2. Stocker dans une variable R1 le corps des réels à une précision de \(1\) bit.

  3. Quelle puissance de \(2\) (éventuellement d’exposant négatif) est la plus proche de \(1/7\) ? Effectuer une coercion de x dans R1, puis vérifier votre réponse.

  4. Stocker dans une variable R3 le corps des réels à une précision de \(3\) bits.

  5. Effectuer une coercion de x dans R3, puis retrouver la mantisse et l’exposant correspondant. On pourra également s’aider de la méthode .sign_mantissa_exponent().

  6. En effectuant une coercion de x dans une structure appropriée, donner les \(100\) premières décimales de \(1/7\).

x = 1/7
R1 = RealField(1)

La puissance de \(2\) la plus proche de \(1/7\) est \(2^{-3} = 1/8\). Vérifions-le :

R1(x) == 1/8
True
R3 = RealField(3)
y = R3(x)
y.sign_mantissa_exponent()
(1, 5, -5)

La mantisse vaut \(5\) et l’exposant \(-5\). En effet, le nombre représenté sur \(3\) bits le plus proche de \(17\) est \(\frac{5}{32} = 2^{-3} + 2^{-5} = 5 \times 2^{-5}\). On le vérifie une nouvelle fois :

print(y)
print(y == 5/32)
0.16
True

Enfin, les \(100\) premières décimales de \(1/7\) sont :

nombres_bits = ceil(100*log(10,2))
print(RealField(nombres_bits)(x))
0.142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857142857143

Exercice 2. Affichage graphique simple#

Question 1 : Tracer sur un même graphique les fonctions cosinus (en bleu) et sinus (en rouge), entre \(0\) et \(4\pi\).

plot(cos, [0, 4*pi], color="blue") +  plot(sin, [0, 4*pi], color="red")
../_images/e4ba7daaf02bf69751d92fabb636163ff7676e32a17ca9a1747a3b1fac2faadb.png

Question 2 :

  • Tracer la fonction tangente entre \(-\pi\) et \(\pi\).

  • Puis, essayer de rendre le tracé plus « représentatif » en imposant une valeur maximale et minimale à l’ordonnée.

  • Pourquoi pensez-vous qu’il y a des droites verticales ? Les retirer en ajoutant l’argument optionnel detect_poles=True dans la fonction plot().

plot(tan, [-pi, pi])
../_images/8d6f2a38ea9d19b814cd36977ce6b1181932b131cda6c5b999a186fe55e72f17.png
plot(tan, [-pi, pi], ymax = 10, ymin = -10)
../_images/1580b1a62094760f2b804ba7fcdc9c49de161ae2a27701f13bb8111ecb6b7eba.png
plot(tan, [-pi, pi], ymax = 10, ymin = -10, detect_poles=True)
../_images/5d0c3a11236d3c17a7ccbb852e383dff3b011d8e536331c2fb873fbf18d7bbb6.png

Exercice 3. Série harmonique#

On considère la suite \((H_n)_{n \ge 1}\) définie comme : \(H_n = \sum_{i=1}^n \frac{1}{n}\). Cette suite est appelée « série harmonique ».

Question 1 : Écrire une fonction calcule_H(n) qui prend en entrée un entier naturel n et qui retourne le terme \(H_n\).

def H(n):
    res = 0
    for i in range(1, n+1):
        res += 1/i
    return res
    
print(H(3))
11/6

Question 2 : Tracer sur un même graphique :

  • les \(100\) premiers termes de la suite \(H_n\),

  • la fonction \(\ln(x)\) pour \(x \in [1, 100]\).

Pour tracer les termes de la série harmonique, on rappelle qu’on peut utiliser la fonction points(L) qui prend en entrée une liste de points de la forme \([ (x_1, y_1), \dots, (x_k, y_k) ]\) , et qui retourne un objet graphique (comme le ferait plot) représentant tous les points de coordoonées \((x_i, y_i)\) de la liste.

points([[i, H(i)] for i in range(100)]) + plot(ln, [1, 100], color="red")
../_images/0b14a8b96df80493702e0f724758a1ab83d900ea015da3a73199629c8d2dee1f.png

Question 3 : La différence \(H_n - \ln(n)\) semble converger vers une constante. La calculer approximativement. Pour cela, on pourra calculer des termes de \(u_n := H_n - \ln(n)\) jusqu’à ce que deux termes consécutifs de la suite \((u_n)\) soit distants de moins de \(10^{-8}\).

Indication supplémentaire : comme la convergence est lente, on pourra essayer de :

  • reformuler la valeur de \(u_{n+1}-u_n\) pour éviter de calculer des sommes

  • calculer les \(u_{n+1}-u_n\) avec des ordre \(n\) allant de \(100\) en \(100\) plutôt que de \(1\) et \(1\)

Puis, comparer la valeur obtenue à l’objet euler_gamma de Sagemath.

def calcule_constante():
    n = 2
    eps = 10**(-8)
    e = 1
    while abs(e) > eps :
        # e = H(n) - ln(n) - H(n-1) + ln(n-1) 
        e = 1/n - ln(n/(n-1))
        n += 1
    print("n =", n)
    return H(n)-ln(n)

g = calcule_constante()
print(float(g))
print(float(euler_gamma))
n = 7073
0.5772863545972928
0.5772156649015329

Exercice 4. Produit de Wallis et une mauvaise approximation rationnelle de \(\pi\)#

En 1656, Wallis a démontré que

\[ \frac{\pi}{2} = \prod_{n=1}^\infty \frac{4n^2}{4n^2-1}. \]

Nous allons utiliser cette formule pour obtenir une approximation rationnelle (mais peu efficace) de \(\pi\).

Question 1 : Écrire une fonction produit_wallis(k) qui prend en entrée un entier strictement positif k, et qui retourne le produit

\[ P_k := \prod_{n=1}^k \frac{4n^2}{4n^2-1}. \]

Vérifier ensuite que \(P_1 = \frac{4}{3}\) et que \(P_6 = \frac{1048576}{693693}\).

def produit_wallis(k):
    res = 1
    for n in range(1, k+1):
        res *= (4*n**2)/(4*n**2-1)
    return res

print(produit_wallis(1))
print(produit_wallis(6))
4/3
1048576/693693

Question 2 : Afficher le nombre flottant associé à \(2 P_{100}\), puis vérifier qu’il a au moins une décimale en commun avec \(\pi\).

print(RealField()(2*produit_wallis(100)))
3.13378749062816

Question 3 : Quelle est la plus petite valeur de \(k\) pour laquelle les nombres \(2 P_k\) et \(\pi\) ont au moins \(3\) décimales en commun ? Quel est alors le nombre de chiffres du dénominateur \(d\) de la fraction \(2 P_k\) (calculer la partie entière supérieure de \(\log_{10}(d)\) pour obtenir cela) ?

k = 1
w = produit_wallis(k)
while abs(pi - 2*w) > 10**(-3):
    k += 1
    w = produit_wallis(k)
print(k)
print("Le dénominateur a", ceil(log(w.denominator(), 10)), "chiffres décimaux")
785
Le dénominateur a 943 chiffres décimaux

Remarque : on peut s’épargner des calculs répétés avec les instructions suivantes :

k = 0
w = 1
seuil = 10**(-3)
while abs(pi - 2*w) > seuil:
    k += 1
    t = 4*k**2
    w *= t/(t-1)
print(k)
print("Le dénominateur a", ceil(log(w.denominator(), 10)), "chiffres décimaux")
785
Le dénominateur a 943 chiffres décimaux

Remarque : Cette manière de calculer les décimales de \(\pi\) est donc très peu efficace.