Vous êtes sur la page 1sur 50

Corrigé de l’exercice 12.

1

Corrigés des exercices

# version

def

itérative

palindrome(chaine):

i,

n

=

0,

len(chaine)

-

1

while

 

i

<

n

and

chaine[i]

==

chaine[n]:

i

+=

1

n

-=

1

return

n

<=

i

print(palindrome('ressasser'),

palindrome('ressassir'),

palindrome('serres'))

True

False

True

# version

def

récursive

palindrome(chaine):

if

len(chaine)

<=

1:

return

True

 

if

chaine[0]

!=

chaine[-1]:

return

else:

return

False

palindrome(chaine[1:-1])

print(palindrome('ressasser'),

palindrome('ressassir'),

palindrome('serres'))

True

False

True

# variante

def

return

palindrome(chaine):

chaine

==

chaine[::-1]

print(palindrome('ressasser'),

palindrome('ressassir'),

palindrome('serres'))

True

False

True

2

Programmation en Python pour les mathématiques

Corrigé de l’exercice 13.

def champernowne(n): x = '0.' k = 0 while len(x) <= n+2: k += 1
def
champernowne(n):
x =
'0.'
k =
0
while
len(x)
<=
n+2:
k
+=
1
x
+=
str(k)
return
x[0:n+2]
print(champernowne(75))
# variante
avec
join
def
champernowne(n):
return
'0.'
+
''.join(str(i)
for
i
in
range(1,
n))[:n]

0.123456789101112131415161718192021222324252627282930313233343536373839404142

Corrigé de l’exercice 15.

def cosinus(x, epsilon): p = 0 somme = 1 terme = 1 reste = abs(x)
def
cosinus(x,
epsilon):
p =
0
somme
=
1
terme
=
1
reste
=
abs(x)
while
reste
>
epsilon:
p
+=
2
terme
* =
-
/
(p
*
(p
-
1))
somme
+=
x ** 2
terme
reste
abs(x) ** 2
/
(p
(p
+
1))
* =
*
return
somme
# Pour
la
vérification,
on
peut
utiliser
le
module
math
:
import
math
print(cosinus(1,
1e-5))
print(cosinus(1,
1e-14))
print(math.cos(1))
print(cosinus(math.pi/4,
1e-5))
print(cosinus(math.pi/4,
1e-14))
print(math.sqrt(2)/2)

0.5403025793650793

0.5403023058681398

0.5403023058681398

0.7071068056832942

0.7071067811865475

Corrigés des exercices

3

Corrigé de l’exercice 16.

def

pythagoriciens(n):

 

return

[(x,

y,

z)

for

x

in

range(1,

 

n)

for

y

in

==

range(x, z ** 2]

 

n)

 

for

z

in

range(y,

n)

if

x ** 2

+

y ** 2

 

print(pythagoriciens(101))

 

print("Au

total,

on

trouve

{}

triplets.".format(len(pythagoriciens(101))))

 

[(3,

4,

5),

(5,

12,

13),

(6,

8,

10),

(7,

24,

25),

(8,

 

15,

17),

(9,

12,

15),

 

(9,

40,

41),

 

(10,

24,

26),

(11,

60,

 

61),

(12,

16,

20),

 

(12,

35,

37),

(13,

84,

85),

 

(14,

48,

50),

(15,

20,

25),

(15,

36,

39),

(16,

30,

34),

(16,

63,

65),

(18,

24,

30),

(18,

80,

82),

(20,

21,

29),

(20,

48,

52),

(21,

28,

35),

(21,

72,

75),

(24,

32,

40),

(24,

45,

51),

(24,

70,

74),

(25,

60,

65),

(27,

36,

45),

(28,

45,

53),

(28,

96,

100),

(30,

40,

50),

(30,

72,

78),

(32,

60,

68),

(33,

44,

55),

(33,

56,

65),

(35,

84,

91),

(36,

48,

60),

(36,

77,

85),

(39,

52,

65),

(39,

80,

89),

(40,

42,

58),

(40,

75,

85),

(42,

56,

70),

(45,

60,

75),

(48,

55,

73),

(48,

64,

80),

(51,

68,

85),

(54,

72,

90),

(57,

76,

95),

(60,

63,

87),

(60,

80,

100),

 

(65,

72,

97)]

 

Au

total,

on

trouve

52

triplets.

 

Corrigé de l’exercice 17.

 

for

n

in

range(2,

20):

 

print('

+

'.join('{:2}^2'.format(i)

for

i

in

range(1,

n))

 

+

'

=

{}'.format(sum(i ** 2

for

i

in

range(1,

n))))

 

1^2

=

1

1^2

+

2^2

=

5

1^2

+

2^2

+

3^2

=

14

1^2

+

2^2

+

3^2

+

4^2

=

30

1^2

+

2^2

+

3^2

+

4^2

+

5^2

=

55

1^2

+

2^2

+

3^2

+

4^2

+

5^2

+

6^2

=

91

1^2

+

2^2

+

3^2

+

4^2

+

5^2

+

6^2

+

7^2

=

140

1^2

+

2^2

+

3^2

+

4^2

+

5^2

+

6^2

+

7^2

+

8^2

=

204

 

1^2

+

2^2

+

3^2

+

4^2

+

5^2

+

6^2

+

7^2

+

8^2

+

9^2

=

285

1^2

+

2^2

+

3^2

+

4^2

+

5^2

+

6^2

+

7^2

+

8^2

+

9^2

+

10^2

=

385

1^2

+

2^2

+

3^2

+

4^2

+

5^2

+

6^2

+

7^2

+

8^2

+

9^2

+

10^2

+

11^2

=

506

[

]

Corrigé de l’exercice 18.

 

def

parfait(n):

 

return

sum([d

for

d

in

range(1,

n)

if

n

%

d

==

0])

==

n

def

liste _ parfaits(n):

 

return

[i

for

i

in

range(2,

n)

if

parfait(i)]

 

4

Programmation en Python pour les mathématiques

print(liste _ parfaits(10000))

 

def

somme(n):

 

diviseurs

=

[d

for

d

in

range(1,

n)

if

 

n

%

d

==

0]

if

 

sum(diviseurs)

==

n:

 

print('{}

=

 

'.format(n)

+

'

+

'.join(str(d)

for

d

in

diviseurs))

for

i

in

liste _ parfaits(10000):

 

somme(i)

 

[6,

28,

 

496,

 

8128]

 

6

=

1

+

2

+

3

28

=

1

+

2

+

4

+

7

+

14

 

496

=

1

+

2

+

4

+

8

+

16

+

31

+

62

+

124

+

248

 

8128

=

1

+

2

+

4

+

8

+

16

+

32

+

64

+

127

+

254

 

+

508

+

1016

+

2032

+

4064

Corrigé de l’exercice 19.

def

crible(prems):

 

if

prems

==

[]:

 

return

[]

 

return

[prems[0]]

+

crible([p

for

p

in

prems[1:]

if

p

%

prems[0]

!=

0])

print(crible(range(2,

1000)))

 

[2,

3,

5,

7,

11,

13,

17,

19,

23,

29,

31,

37,

41,

43,

47,

53,

59,

61,

67,

71,

73,

79,

83,

89,

97,

101,

103,

107,

109,

113,

127,

131,

137,

139,

149,

151,

157,

163,

167,

173,

179,

181,

191,

193,

197,

199,

211,

223,

227,

229,

233,

239,

241,

251,

257,

263,

269,

271,

277,

281,

283,

293,

307,

311,

313,

317,

331,

337,

347,

349,

353,

359,

367,

373,

379,

383,

389,

397,

401,

409,

419,

421,

431,

433,

439,

443,

449,

457,

461,

463,

467,

479,

487,

491,

499,

503,

509,

521,

523,

541,

547,

557,

563,

569,

571,

577,

587,

593,

599,

601,

607,

613,

617,

619,

631,

641,

643,

647,

653,

659,

661,

673,

677,

683,

691,

701,

709,

719,

727,

733,

739,

743,

751,

757,

761,

769,

773,

787,

797,

809,

811,

821,

823,

827,

829,

839,

853,

857,

859,

863,

877,

881,

883,

887,

907,

911,

919,

929,

937,

941,

947,

953,

967,

971,

977,

983,

991,

997]

 

Corrigé de l’exercice 27.

2

Corrigés des exercices

import os import sys def parcours(repertoire): arborescence = os.walk(repertoire) for dossier in arborescence:
import
os
import
sys
def
parcours(repertoire):
arborescence
=
os.walk(repertoire)
for
dossier
in
arborescence:
for
fichier
in
dossier[2]:
if
fichier.endswith('.py'):
print(os.path.join(dossier[0],
fichier))
#variante
:
print(os.path.abspath(fichier))
if
name
==
"
main
":
try:
parcours(sys.argv[1])
except
IndexError:
parcours(os.getcwd())

Corrigé de l’exercice 28.

from math import * import sys sys.path.append(' /modules') / from PostScript import * def
from
math
import
*
import
sys
sys.path.append('
/modules') /
from
PostScript
import
*
def
rectangle(base,
k):
[A,
B]
=
base
norme
=
hypot(B[0]
-
A[0],
B[1]
-
A[1])
orthog
=
[A[1]-B[1],
B[0]-A[0]]
D
=
[a
+
k * u
for
(a,
u)
in
zip(A,
orthog)]
C
=
[b
+
return
[A,
k * u
B,
for
(b,
u)
in
zip(B,
orthog)]
C,
D]

6

Programmation en Python pour les mathématiques

def triangle(base, theta): [A, B] = base C = [b - a for (a, b)
def
triangle(base,
theta):
[A,
B]
=
base
C
=
[b
-
a
for
(a,
b)
in
zip(A,
B)]
R
=
[(1+cos(2 * theta))/2,
sin(2 * theta)/2]
C
=
[R[0] * C[0]
R[1] * C[0]
-
R[1] * C[1],
+
R[0] * C[1]]
C
=
[a
+
c
for
(a,
c)
in
zip(A,
C)]
return
[A,
B,
C]
def
pythagore(base,
k,
theta,
niveau,
N=None):
if
N
==
None:
N
=
niveau
q
=
niveau/N
couleur
=
(q,
4 * q * (1-q),
(1-q))
#
arbre
multicolore
rc
=
rectangle(base,
k)
graphique.ajouteCourbe(rc,
couleur,
fill=True)
tr
=
triangle(rc[:-3:-1],
theta)
if
niveau
>
1:
pythagore([tr[0],
tr[2]],
k,
theta,
niveau
-
1,
N)
pythagore([tr[2],
tr[1]],
k,
theta,
niveau
-
1,
N)
if
name
==
"
main
":
N
=
14
base
=
[[0,
0],
[2,
0]]
nomFichier
=
"pythagore"
boite
=
[-8,
-1,
6,
9]
zoom,
marge,
ratioY,
trait
=
30,
1.02,
1,
0.1
graphique
=
Plot(nomFichier,
boite,
zoom,
marge,
ratioY)
graphique.preambule()
graphique.cadre()
pythagore(base,
0.9,
pi/6,
N)
graphique.fin()
graphique.exportePDF()
graphique.affichePS()
Corrigé de l’exercice 29.
a)
Tracé d’une courbe en polaire.
import
numpy
as
np
import
matplotlib.pyplot
as
plt
theta
=
np.linspace(0,
1
+
int(38 * np.pi),
1000)
r
=
1
+
np.cos(20
*
theta
/
19)
/
3
plt.polar(theta,
r,
linewidth=0.8)
plt.show()

Corrigés des exercices

7

b) Tracé d’une surface 3D.

from mpl _ toolkits.mplot3d import Axes3D from matplotlib import cm import matplotlib.pyplot as plt import
from
mpl _ toolkits.mplot3d
import
Axes3D
from
matplotlib
import
cm
import
matplotlib.pyplot
as
plt
import
numpy
as
np
fig
=
plt.figure()
ax
=
Axes3D(fig)
X =
np.arange(-3,
3,
0.07)
Y =
np.arange(-3,
3,
0.07)
X,
Y
=
np.meshgrid(X,
Y)
Z =
X
*
Y
/
(X ** 2
+
Y ** 2)
ax.plot _ surface(X,
Y,
Z,
linewidth=0.1,
rstride=1,
cstride=1,
cmap=cm.jet)
ax.set _ xlabel('X')
ax.set _ ylabel('Y')
ax.set _ zlabel('Z')
plt.show()

cmap=cm.jet) ax.set _ xlabel('X') ax.set _ ylabel('Y') ax.set _ zlabel('Z') plt.show()

3

Corrigés des exercices

Corrigé de l’exercice 40.

Maintenant, on effectue 7 multiplications matricielles (n 3 multiplications élémentaires) mais 18 additions (n 2 additions élémentaires). Les multiplications matricielles étant plus coûteuses, théoriquement on gagne en efficacité pour les grandes matrices. On obtient en effet une complexité en Θ(n log 2 n ) au lieu de Θ(n 3 ). Si la taille des matrices n’est pas une racine de 2, on complète avec des zéros. On crée donc une fonction qui calcule la puissance de 2 directement supérieure :

def

next _ pow _ 2(x):

return

2 ** (ceil(log(x)/log(2)))

Puis une fonction qui découpe une matrice en quatre blocs carrés après avoir complété avec des zéros :

matrice.py

def

coupe _ en _ 4(self):

[r,c]

=

self.D

t

=

max(next _ pow _ 2(r),next _ pow _ 2(c))

 

m

=

Mat([t,t],

lambda

i,j:

self[i,j]

if

(i

<

r

and

j

<

c)

else

0)

s

=

t//2

A

=

Mat([s,

s],

lambda

i,j:

m[i

,j

])

B

=

Mat([s,

s],

lambda

i,j:

m[i

,j

+

s])

C

=

Mat([s,

s],

lambda

i,j:

m[i

+

s,j

])

D

=

Mat([s,

s],

lambda

i,j:

m[i

+

s,j

+

s])

return(A,B,C,D)

Enfin, on applique les calculs de STRASSEN récursivement jusqu’à une limite de 32 (qui cor- respond théoriquement à la limite d’efficacité de l’algo par rapport au nombre d’additions qui deviennent trop gourmandes) et on découpe la matrice obtenue selon la taille attendue :

matrice.py

def

strassen(self,other):

ld

=

self.D

+

other.D

t

=

max(map(next _ pow _ 2,ld))

if

t

<=

32:

return

self * other

a,b,c,d

=

self.coupe _ en _ 4()

e,f,g,h

=

other.coupe _ en _ 4()

[li,co]

=

a.D

Corrigés des exercices

9

p1 = a.strassen(f - h) p2 = (a + b).strassen(h) p3 = (c + d).strassen(e)
p1
=
a.strassen(f
-
h)
p2
=
(a
+
b).strassen(h)
p3
=
(c
+
d).strassen(e)
p4
=
d.strassen(g
-
e)
p5
=
(a
+
d).strassen(e
+
h)
p6
=
(b
-
d).strassen(g
+
h)
p7
=
(c
-
a).strassen(e
+
f)
w
=
p4
+
p5
+
p6
-
p2
x
=
p1
+
p2
y
=
p3
+
p4
z
=
p1
+
p5
-
p3
+
p7
def
fs(i,j):
if
i
<
li:
if
j
<
li:
return
w.F(i,j)
else:
return
x.F(i,j
-
li)
elif
j
<
li:
return
y.F(i
-
li,j)
else:
return
z.F(i
-
li,j
-
li)
return
Mat(self.D,
fs)

Corrigé de l’exercice 41.

def

contour(m):

 

[li,co]

=

m.D

return

Mat([li

-

2,

co

-

2],

 

lambda

i,j

:

floor(sqrt((m[i,j-1]-m[i,j+1]) ** 2

+

 

(m[i-1,j]-m[i+1,j]) ** 2))

 

)

ou

def

contour(m):

 

[li,co]

=

m.D

return

Mat([li

-

2,

co

-

2],

 

lambda

i,j

:

255

-

floor(sqrt((m[i,j-1]-m[i,j+1]) ** 2

+

 

(m[i-1,j]-m[i+1,j]) ** 2))

 
 

)

On obtient alors au choix, avec cette fois Lena de trois-quarts qui a plus de sauts de niveaux :

2))     ) On obtient alors au choix, avec cette fois Lena de trois-quarts qui

10

Programmation en Python pour les mathématiques

10 Programmation en Python pour les mathématiques Corrigé de l’exercice 44 . L’accumulateur est nul au

Corrigé de l’exercice 44.

L’accumulateur est nul au départ. L’alternative peut être évitée en multipliant y par le reste de la division de x par 2

1 Fonction MULRUSSE( x:entier ,y: entier, acc:entier ):entier

2 Si x == 0 Alors

3 Retourner acc

4 Sinon

5 Retourner MULRUSSE(x // 2, y*2, acc + y*(x % 2))

6 FinSi

Ce qui donne :

Bits.py

def mul _ russe(self,other): """Algo de la multiplication du paysan russe""" op1,op2 =
def
mul _ russe(self,other):
"""Algo
de
la
multiplication
du
paysan
russe"""
op1,op2
=
self.norm(),other.norm()
if
op1[0]
==
1:
return
-((-op1).mul _ russe(op2))
if
op2[0]
==
1:
return
-(op1.mul _ russe(-op2))
def
aux(acc,x,y):
if
x
==
Bits([0,0]):
return
acc
return
aux(acc
+
(Bits([0,0])
if
x.pair()
else
y),
Bits(x[:-1]),
Bits(y.bits
+
[0]))
return
aux(Bits([0,0]),op1,op2)

Corrigé de l’exercice 45.

Bits.py

def

mul _ karat(self,

"""Algo

de

other):

Karatsouba"""

Corrigés des exercices

11

op1,op2

=

self.norm(),other.norm()

if

op1.signe()

==

1:

return

-((-op1).mul _ karat(op2))

if

op2.signe()

==

1:

return

-(op1.mul _ karat(-op2))

long

=

max(len(op1),

len(op2))

 

op1

=

Bits([0

for

i

in

range(len(op1),

long)]

+

op1.bits)

op2

=

Bits([0

for

i

in

range(len(op2),

long)]

+

op2.bits)

if

long

<=

2:

 
 

return

Bits([0,

 

op1[1]

&

op2[1]])

 

m0

=

(long

+

1)

>>

1

m1

=

long

>>

1

x0

=

Bits([0]

+

 

op1[

 

:

m0]).norm()

 

x1

=

Bits([0]

+

op1[m0

:

]).norm()

y0

=

Bits([0]

+

op2[

 

:

m0]).norm()

y1

=

Bits([0]

+

op2[m0

:

]).norm()

p0

=

x0.mul _ karat(y0)

 

p1

=

(x0

-

x1).mul _ divis(y0

-

y1)

 

p2

=

x1.mul _ divis(y1)

 

z0

=

Bits(p0.bits

+

 

[0

for

i

in

range(0,

m1

<<

1)])

z1

=

Bits((p0

+

 

p2

-

p1).bits

+

[0

for

i

in

range(0,

m1)])

z2

=

p2

return

z0

+

z1

+

z2

Vous remarquerez que les deux dernières multiplications sont moins efficaces avec cette im- plémentation : en effet, nos additions sont coûteuses contrairement à ce qui se passe sur ma- chine.

#mul _ russe In [48]: %timeit (n * n) 1000 loops, best of 3: 525
#mul _ russe
In
[48]:
%timeit
(n
*
n)
1000
loops,
best
of
3:
525
µs
per
loop
#mul _ karat
In
[51]:
%timeit
(n
n)
*
100
loops,
best
of
3:
3.14
ms
per
loop
#mul _ divis
In
[54]:
%timeit
(n
*
n)
100
loops,
best
of
3:
7.08
ms
per
loop
#mul _ primaire
In
[57]:
%timeit
(n
*
n)
1000 loops,
best
of
3:
576
µs
per
loop

12

Programmation en Python pour les mathématiques

Corrigé de l’exercice 46.

On se rappelle que les 5 heures 48’55” sont causes de la création des années bissextiles : les années dont les millésimes sont des multiples de 4 ont 366 jours sauf les fins de siècles qui ne sont pas des multiples de 400 mais cela reste approximatif. En étudiant les fractions continues, Grégoire XIII aurait pu être plus précis. Pour cela, étudions la suite des différences des réduites successives.

In

[1]:

F

=

rationnel(5,24)

 

+

rationnel(48,24 * 60)

+

rationnel(55,24 * 60 * 60)

 

In

[2]:

Q

=

fci(F)

 

In

[3]:

[reduite(k

+

1,

Q)

-

reduite(k,

Q)

for

k

in

range(7)]

 

Out[3]:

[1

/

4,

-1

/

116,

1

/

957,

-1

/

7491,

1

/

59020,

-1

/

194220,

1

/

1310238]

Ainsi qu’une année est égale en jours à :

 
 

1

1

1

1

1

1

1

365 +

4 116 + 957 7 491 + 59 020 194 220 + 1 310 238 +···

On obtient ainsi que tous les 4 ans il faut rajouter un jour, en enlever 1 tous les 116 ans, en rajouter 1 tous les 957 ans, etc.

Corrigé de l’exercice 47.

On cherche avec base1 à déterminer à partie de quelle puissance de 2 la plus petite distance entre deux nombres VF devient plus grande que 1 : on aura ainsi atteint la taille de la mantisse. Dans base2, on prend pour a la valeur trouvée précédemment. Rappelons le mécanisme de calcul de 2 ** 53 + 1 :

1,0000000000000000000000000000000000000000000000000000|

0,0000000000000000000000000000000000000000000000000000|1

--------------------------------------------------------

1,0000000000000000000000000000000000000000000000000000|1

et 2 ** 53

+

2 :

1,0000000000000000000000000000000000000000000000000000|

0,0000000000000000000000000000000000000000000000000001|0

--------------------------------------------------------

1,0000000000000000000000000000000000000000000000000001|0

On a effectué ce « saut » hors de la zone d’erreur car on a atteint la base. Ainsi la valeur finale de b permet de déterminer la base de calcul du système qui est en général 2. Un contre-exemple notoire est le logiciel Maple qui travaille en base 10. De manière plus rigoureuse, on peut raisonner dans V β l’espace des VF de base β. Notons R la fonction d’arrondi. Les lignes 4 à 6 construisent une suite a i = R(2a i1 ) avec a 0 = 1.0 mais est-on sûr que l’on a toujours a i = 2 i dans ces conditions ? On démontre d’abord par récurrence que a i = R(2 i ) = 2 i tant que i vérifie 2 i β p 1 : 2 i = 2×2 i1 est un entier qui s’écrit avec moins de p chiffres de la base β et en deçà de β p 1, on peut passer d’un flottant à son successeur par des pas inférieurs à 1. Alors R(a i + 1.0) = a i + 1.0 : pas d’arrondi.

Corrigés des exercices

13

Puis R(R(a i + 1.0) a i ) = R(a i + 1.0 a i ) = 1.0 : la condition de la première boucle est donc vérifiée tant que 2 i < β p . Que se passe-t-il après ? Dès que β p 1 est atteint, les choses changent. Considérons la première itération i s telle que 2 i s β p . On a

a i s = R(2 × a i s 1 ) = R(2 × 2 i s 1 ) < R(2 × β p ) R(β × β p ) = β p+1

car d’une part a i s 1 = 2 i s 1 , d’autre part a i s 1 β p 1 < β p et enfin 2 β. Ainsi

β p

a i s < β p+1

L’exposant de la forme normale de a i s est donc p et le successeur d’un VF v vérifie (en notant n = p 1 la longueur de la pseudo-mantisse) :

succ(v) = v + β E(v)n = v +β E(v)p+1

Ici succ(a i s ) = a i s +β E(a i s p+1) = a i s +β pp+1 = a i s +β. On en déduit que a i s + 1.0 est entre a i s et son successeur a i s +β. Donc, selon l’arrondi, R(a i s + 1.0) vaut a i s ou a i s + β et finalement R(R(a i s + 1.0) a i s ) vaut 0 ou β mais en aucun cas 1.0 : on sort donc de la boucle.

On en déduit que boucle1 1 vaut a i s donc que β p boucle1 1 < β p+1

Notons a = boucle1 1. Son successeur est a + β. On démontre alors la seconde boucle. Cette démonstration est plutôt technique et difficile en première lecture. Cependant elle est pleine d’enseignements :

elle nous montre bien que nous changeons de monde : un test du style if (a + 1.0)-

a /= 1.0 paraîtrait bien hors de propos si nous raisonnions avec des réels ;

nous avons vu que l’on pouvait raisonner rigoureusement sur les VF ;

nous pouvons malgré tout retenir la trame intuitive de la démonstration : tant que notre nombre entier est représentable avec p chiffres, on reste exact. Les problèmes arrivent lorsqu’on n’a plus assez de place pour stocker tous les chiffres : il y a de la perte d’infor- mation

Ce genre de raisonnement se retrouve très souvent pour travailler sur les erreurs com- mises : il faudra donc en retenir la substantifique moelle

N’oubliez pas que certains langages ne travaillent pas en base 2 :

MAPLE

> a := 1.0: > b := 1.0: > while evalf(evalf(a + 1.0) - a)
> a
:=
1.0:
> b
:=
1.0:
> while
evalf(evalf(a
+
1.0)
-
a)
-
1.0
=
0.0
do
a :=
2.0
a;
*
od:
> evalf(evalf(a
while
+
b)
-
a)
-
b
<>
0.0
do
b :=
b
+
1.0
od:
> b;
10.0

14

Programmation en Python pour les mathématiques

Corrigé de l’exercice 48. Il est aisé de montrer que la probabilité que la tortue gagne Pr(T) est égale à 6 5 6 0, 335.

def jeutortue(n): [L,T] = [0,0] for simul in range(n): face = randint(1,6) lancer = 1
def
jeutortue(n):
[L,T]
=
[0,0]
for
simul
in
range(n):
face
=
randint(1,6)
lancer
=
1
while
face
<
6
and
lancer
<
6:
face
=
randint(1,6)
lancer
+=
1
if
face
==
6
:
L
+=
1
else
:
T
+=
1
return
'Tortue
:'+str(T * 100.0/n)+'%
Lièvre
:
'+str(L * 100.0/n)+'%'

Pour un million de simulations :

>>>

jeutortue(1000000)

:33.4824%

'Tortue

Lièvre

:

66.5176%'

Corrigé de l’exercice 52.

4

Corrigés des exercices

>>>

import

numpy

as

np

>>>

from

scipy

import

optimize

 

>>>

optimize.bisect(lambda

x:np.cos(x)-x,

0,

1)

#

par

dichotomie

 

0.7390851332156672

 

>>>

optimize.newton(lambda

x:np.cos(x)-x,

1)

#

par

la

méthode

de

Newton

0.73908513321516067

 

>>>

optimize.brentq(lambda

x:np.cos(x)-x,

0,

1)

#

par

la

méthode

de

Brent

0.7390851332151559

 

>>>

optimize.fixed _ point(lambda

x:np.cos(x),

1)

#

par

la

méthode

de

Steffensen

0.73908513321516067

 

>>>

optimize.fsolve(lambda

x:np.cos(x)-x,

1)

#

valable

aussi

avec

des

systèmes

array([

0.73908513])

 

Corrigé de l’exercice 51.

 

import

numpy

 

class

ODE(object):

 
 

def

init

(self,

f,

h):

 

self.f

=

lambda

u,

t:

numpy.asarray(f(u,

 

t),

float)

#

1ère

modification

self.h

=

h

def

iteration(self):

 

raise

NotImplementedError

 

def

CI(self,

t0,

x0):

 

self.liste

=

[[t0,

numpy.asarray(x0,

float)]]

 

#

2ème

modification

self.k

=

0

def

resolution(self,

a,

b,

termine=None):

 

if

termine

is

None:

 

termine

=

lambda

x:

False

 
 

self.indice

=

-1

while

(self.liste[-1][0]

<=

b

and

 

not

termine(self.liste[-1][1])):

 
 

self.liste.append(self.iteration())

16

Programmation en Python pour les mathématiques

self.h = - self.h self.indice = 0 while (self.liste[0][0] >= a and not termine(self.liste[0][1])):
self.h
=
-
self.h
self.indice
=
0
while
(self.liste[0][0]
>=
a
and
not
termine(self.liste[0][1])):
self.liste.insert(0,
self.iteration())
return
self.liste
class
Euler(ODE):
def
iteration(self):
f,
h
=
self.f,
self.h
[t,
x]
=
self.liste[self.indice]
return
[t
+
h,
x
+
h
*
f(t,
x)]
class
RK4(ODE):
def
iteration(self):
f,
h
=
self.f,
self.h
[t,
x]
=
self.liste[self.indice]
k1
=
h
*
f(t,
x)
k2
=
h
*
f(t
+
h/2,
x
+
k1/2)
k3
=
h
*
f(t
+
h/2,
x
+
k2/2)
k4
=
h
*
f(t
+
h,
x
+
k3)
return
[t
+
h,
x
+
(k1
+
2 * k2
+
2 * k3
+
k4)
/
6]
if
name
==
'
main
':
from
math
import
exp,
sin,
cos
import
sys
sys.path.append('
/
/modules')
sys.path.append('modules')
import
PostScript
as
ps
######################################
###
L'exponentielle
:
Euler
vs
RK4
###
######################################
print("Résolution
numérique
du
système
x'(t)
=
x(t)
et
x(0)
=
1
"
"par
la
méthode
d'Euler
et
par
la
méthode
de
Runge
Kutta
d'ordre
4")
def
f(t,
x):
return
x
a,
b,
h
=
0,
1,
0.1
liste _ exacte
=
((t,
exp(t))
for
t
in
ps.srange(a,
b,
h))
print("{:^10}
|
{:^17}
|
{:^17}"
.format('h',
print('-' * 52)
'erreur
euler',
'erreur
rk4'))

Corrigés des exercices

17

for i in range(1, 6): h = 10 ** (-i) euler = Euler(f, h) euler.CI(0,
for
i
in
range(1,
6):
h
=
10 ** (-i)
euler
=
Euler(f,
h)
euler.CI(0,
1.0)
e =
euler.resolution(a,
b)[-1]
rk4
=
RK4(f,
h)
rk4.CI(0,
1.0)
r =
rk4.resolution(a,
b)[-1]
print("{0:>10g}
|
{1:>
.10e}
|
{2:>
.10e}
"
.format(h,
exp(e[0])
-
e[1],
exp(r[0])
-
r[1]))
######################################################################
###
Un
exemple
d'équation
différentielle
non
linéaire
du
1er
ordre
###
######################################################################
print("Résolution
numérique
de
l'équation
x'(t)
=
1
+
t^2
x(t)^2
"
*
"par
la
méthode
de
Runge
Kutta
d'ordre
4")
def
f(t,
x):
return
1
+
t ** 2
*
x ** 2
a,