mercredi 2005 : Pascal, deuxième semestre, DEUG première année, MASS 2004--2005
mercredi 9 février 2005 : enregistrements, nombres complexes
mercredi 16 février 2005 : enregistrements
mercredi 23 février 2005 : tableaux : vecteurs
mercredi 9 mars 2005 : tableaux : matrices
mercredi 16 mars 2005 : tableaux
mercredi 23 mars 2005 : fichiers text
mercredi 30 mars 2005 : fichiers binaires
mercredi 6 avril 2005 : fichiers
mercredi 13 avril 2005 : système d'équations linéaires
mercredi 20 avril 2005 : polynômes
mercredi 11 mai 2005 : tableaux à deux dimensions
mercredi 18 mai 2005 : méthode de Newton
mercredi 25 mai 2005 : dichotomie
mercredi 1er juin 2005 : affichage de tableaux carrés
suivant sommaire
mercredi 9 février 2005 : enregistrements, nombres complexes
On veut écrire un programme qui lit trois nombres complexes et affiche leur produit.
Donnez un nombre complexe : 1 2
Donnez un nombre complexe : 2 3
Donnez un nombre complexe : 3 4
(1.000+i2.000)(2.000+i3.000)(3.000+i4.000)=(-40.000+i5.000)
première version, sans enregistrement ni procédure
var ar,ai,br,bi,cr,ci,abr,abi,abcr,abci:real;
begin
write('Donnez un nombre complexe : ');
readln(ar,ai);
write('Donnez un nombre complexe : ');
readln(br,bi);
write('Donnez un nombre complexe : ');
readln(cr,ci);
abr:=ar*br-ai*bi;
abi:=ar*bi+ai*br;
abcr:=abr*cr-abi*ci;
abci:=abr*ci+abi*cr;
writeln('(',ar:0:3,'+i',ai:0:3,')',
'(',br:0:3,'+i',bi:0:3,')',
'(',cr:0:3,'+i',ci:0:3,')=',
'(',abcr:0:3,'+i',abci:0:3,')')
end.
deuxième version, sans enregistrement, avec procédures
procedure lit_c(var re,im:real);
begin
write('Donnez un nombre real : ');
readln(re,im)
end;
procedure mul_c(ar,ai,br,bi:real;var cr,ci:real);
begin
cr:=ar*br-ai*bi;
ci:=ar*bi+ai*br
end;
procedure ecrit_c(re,im:real);
begin
write('(',re:0:3,'+i',im:0:3,')')
end;
var ar,ai,br,bi,cr,ci,abr,abi,abcr,abci:real;
begin
lit_c(ar,ai);
lit_c(br,bi);
lit_c(cr,ci);
mul_c(ar,ai,br,bi,abr,abi);
mul_c(abr,abi,cr,ci,abcr,abci);
ecrit_c(ar,ai);
ecrit_c(br,bi);
ecrit_c(cr,ci);
write('=');
ecrit_c(abcr,abci);
writeln
end.
troisième version, avec enregistrements, sans procédure
var a,b,c,ab,abc:record re,im:real end;
begin
write('Donnez un nombre complexe : ');
readln(a.re,a.im);
write('Donnez un nombre complexe : ');
readln(b.re,b.im);
write('Donnez un nombre complexe : ');
readln(c.re,c.im);
ab.re:=a.re*b.re-a.im*b.im;
ab.im:=a.re*b.im+a.im*b.re;
abc.re:=ab.re*c.re-ab.im*c.im;
abc.im:=ab.re*c.im+ab.im*c.re;
writeln('(',a.re:0:3,'+i',a.im:0:3,')',
'(',b.re:0:3,'+i',b.im:0:3,')',
'(',c.re:0:3,'+i',c.im:0:3,')=',
'(',abc.re:0:3,'+i',abc.im:0:3,')')
end.
quatrième version, avec enregistrements et procédures
type complexe=record re,im:real end;
procedure lit_c(var a:complexe);
begin
write('Donnez un nombre complexe : ');
readln(a.re,a.im)
end;
procedure mul_c(a,b:complexe;var c:complexe);
begin
c.re:=a.re*b.re-a.im*b.im;
c.im:=a.re*b.im+a.im*b.re
end;
procedure ecrit_c(a:complexe);
begin
write('(',a.re:0:3,'+i',a.im:0:3,')')
end;
var a,b,c,ab,abc:complexe;
begin
lit_c(a);
lit_c(b);
lit_c(c);
mul_c(a,b,ab);
mul_c(ab,c,abc);
ecrit_c(a);
ecrit_c(b);
ecrit_c(c);
write('=');
ecrit_c(abc);
writeln
end.
On peut écrire d'autres opérations sur les nombres complexes
procedure add_c(a,b:complexe;var c:complexe);
begin
c.re:=a.re+b.re;
c.im:=a.im+b.im
end;
procedure sou_c(a,b:complexe;var c:complexe);
begin
c.re:=a.re-b.re;
c.im:=a.im-b.im
end;
procedure div_c(a,b:complexe;var c:complexe);
var n:real;
begin
n:=sqr(b.re)+sqr(b.im);
c.re:=( a.re*b.re+a.im*b.im)/n;
c.im:=(-a.re*b.im+a.im*b.re)/n
end;
TD : nombres rationnels
Compléter le programme :
type entier=longint;
fraction=record num,den:entier end;
function pgcd(a,b:entier):entier;
...
procedure reduit_frac(var a:fraction);
...
procedure lire_frac(var a:fraction);
begin
...
reduit_frac(a)
end;
procedure ecrire_frac(a:fraction);
...
procedure addition_frac(a,b:fraction;var c:fraction); // c:=a+b
...
procedure soustraction_frac(a,b:fraction;var c:fraction); // c:=a+b
...
var x,y,z:fraction;
begin
write('Donnez deux fractions : ');
lire_frac(x);
lire_frac(y);
addition(x,y,z);
ecrire_frac(x); write('+'); ecrire_frac(y); write('='); ecrire_frac(z); writeln;
...
Quand on l'exécute on doit voir sur l'écran :
Donnez deux fractions : 1 2 2 3
(1/2)+(2/3)=(7/6)
(1/2)-(2/3)=(-1/6)
(1/2)*(2/3)=(1/3)
(1/2)/(2/3)=(3/4)
pgcd
Pour calculer le pgcd de a et b on peut utiliser l'algorithme d'Euclide :
tant que b≠0 faire
a:=a mod b
échanger a et b
fait
A la fin, la valeur cherchée est dans a.
grands nombres
Le programme devra marcher avec des grands nombres comme :
(1/1001000)+(1/999000)=(2/999999)
(2/999999)-(1/999000)=(1/1001000)
(1002000/999999)*(999000/1003002)=(1000000/1002001)
Pour cela il faut utiliser les algorithmes suivants :
addition
Les calculs à faire pour obtenir (e/f)=(a/b)+(c/d) sont :
p=pgcd(b,d)
B=b/p
D=d/p
E=a*D+c*B
q=pgcd(E,p)
e=E/q
f=(p/q)*B*D
car
a c a c 1 a c 1 aD+cB E E/q e
- + - = -- + -- = - (- + -) = - ----- = --- = ------- = -
b d pB pD p B D p BD pBD (p/q)BD f
Si on suppose que a/b et c/d sont irréductibles, on fait ainsi toutes les
simplifications possibles. e/f est déjà réduite.
En effet comme B est premier avec a et avec D, il l'est aussi avec aD et donc aussi avec E.
Il n'y a donc pas de simplification possible entre E et B, (ni entre E et D).
On peut aussi ranger E dans le numérateur du résultat, et p dans son dénominateur,
puis réduire cette fraction (en appelant la procédure de réduction) et
enfin multiplier son dénominateur par BD.
multiplication
Les calculs à faire pour obtenir (e/f)=(a/b)*(c/d) sont :
p=pgcd(a,d)
q=pgcd(b,c)
e=(a/p)*(c/q)
f=(b/q)*(d/p)
car
a c c a c/q a/p e
- - = - - = --- --- = -
b d b d b/q d/p f
Si on suppose que a/b et c/d sont irréductibles, on fait ainsi toutes les
simplifications possibles. e/f est déjà réduite.
On peut aussi échanger les numérateurs des deux fractions à multiplier, puis les réduire
(en appelant la procédure de réduction) avant de faire le produit des numérateurs et
le produit des dénominateurs.
Autres calculs sur des fractions
Modifier le programme pour obtenir quand on l'exécute :
Donnez deux entiers : 9 11
La somme des inverses des nombres entiers de 9 à 11 est (299/990)
L'algorithme à utiliser est :
s:=0
pour i:=x, x+1, ... y faire
t:=1/i
s:=s+t
fait
s et t sont des fractions.
Donc s:=0 consiste à ranger 0 et 1 dans le numérateur et le dénominateur de s.
De même t:=1/i consiste à ranger 1 et i dans le numérateur et le dénominateur de t.
Enfin s:=s+t se traduit par un appel à la procédure addition_frac.
suivant précédent sommaire
mercredi 16 février 2005 : enregistrements
racine carrée d'un nombre complexe et équation du second degré à coefficients complexes
type complexe=record re,im:real end;
procedure lit_c(var a:complexe);
begin
write('Donnez un nombre complexe : ');
readln(a.re,a.im)
end;
procedure ecrit_c(a:complexe);
begin
write('(',a.re:0:3,'+i',a.im:0:3,')')
end;
procedure mul_c(a,b:complexe;var c:complexe);
begin
c.re:=a.re*b.re-a.im*b.im;
c.im:=a.re*b.im+a.im*b.re
end;
procedure add_c(a,b:complexe;var c:complexe);
begin
c.re:=a.re+b.re;
c.im:=a.im+b.im
end;
procedure sou_c(a,b:complexe;var c:complexe);
begin
c.re:=a.re-b.re;
c.im:=a.im-b.im
end;
procedure div_c(a,b:complexe;var c:complexe);
var n:real;
begin
n:=sqr(b.re)+sqr(b.im);
c.re:=( a.re*b.re+a.im*b.im)/n;
c.im:=(-a.re*b.im+a.im*b.re)/n
end;
function module(a:complexe):real;
begin
module:=sqrt(sqr(a.re)+sqr(a.im))
end;
procedure rac_c(z:complexe;var r:complexe);
var m:real;
begin
m:=module(z);
if m=0 then r:=z else
if z.re>0 then begin r.re:=sqrt((m+z.re)/2); r.im:=z.im/(2*r.re) end
else begin r.im:=sqrt((m-z.re)/2); r.re:=z.im/(2*r.im) end
end;
var a,b,c,d,z1,z2:complexe;
begin
writeln('Donnez les trois coefficients de l''équation du second degré :');
lit_c(a);
lit_c(b);
lit_c(c);
write('L''équation ');ecrit_c(a);write('X*X+');ecrit_c(b);write('X+');ecrit_c(c);
write('=0 a pour solutions ');
b.re:=b.re/-2;
b.im:=b.im/-2;
mul_c(b,b,z1);
mul_c(a,c,z2);
sou_c(z1,z2,d);
rac_c(d,d);
add_c(b,d,z1); div_c(z1,a,z1);
sou_c(b,d,z2); div_c(z2,a,z2);
if module(z2)>module(z1) then z1:=z2;
div_c(c,a,z2);
div_c(z2,z1,z2);
ecrit_c(z1); write(' et ');
ecrit_c(z2); readln
end.
voitures
Les enregistrements peuvent contenir des champs de types différents.
type voiture=record
immatriculation:string[10];
contenu,capacite:real; // du réservoir
kilometrage:real;
end;
procedure roule(var v:voiture;distance,consommation:real);
begin
v.kilometrage:=v.kilometrage+distance;
v.contenu:=v.contenu-consommation;
if v.contenu<0 then
begin
write('La voiture immatriculée ',v.immatriculation,' est tombée en panne sèche.');
readln;
halt
end
end;
procedure plein(var v:voiture);
begin
with v do contenu:=capacite
end;
procedure siphonnage(var v1,v2:voiture;quantite:real);
begin
if v1.contenuv2.capacite then quantite:=v2.capacite-v2.contenu;
v1.contenu:=v1.contenu-quantite;
v2.contenu:=v2.contenu+quantite
end;
procedure affiche(v:voiture);
begin
with v do
writeln('La voiture immatriculée ',immatriculation,' a ',
kilometrage:0:2,' kilomètres au compteur et ',
contenu:0:2,' litres d''essence dans son réservoir, qui peut en contenir ',
capacite:0:2)
end;
var tacot,rouge,bleue:voiture;
begin
tacot.immatriculation:='1234AA75';
tacot.capacite:=100;
tacot.contenu:=40;
tacot.kilometrage:=326621;
rouge.immatriculation:='654CDE75';
rouge.capacite:=40;
rouge.contenu:=4;
rouge.kilometrage:=25231;
bleue:=rouge;
bleue.immatriculation:='655CDE75';
bleue.kilometrage:=27321;
affiche(rouge);
affiche(bleue);
affiche(tacot);
roule(tacot,50,25);
roule(bleue,10,1); // pour aller jusqu'à la pompe
plein(bleue);
roule(bleue,10,1); // pour revenir au garage
siphonnage(bleue,tacot,20);
siphonnage(bleue,rouge,10);
roule(rouge,123,7);
affiche(bleue);
affiche(rouge);
affiche(tacot)
end.
Le programme précédent écrit :
La voiture immatriculée 654CDE75 a 25231.00 kilomètres au compteur et 4.00 litres d'essence dans son réservoir, qui peut en contenir 40.00
La voiture immatriculée 655CDE75 a 27321.00 kilomètres au compteur et 4.00 litres d'essence dans son réservoir, qui peut en contenir 40.00
La voiture immatriculée 1234AA75 a 326621.00 kilomètres au compteur et 40.00 litres d'essence dans son réservoir, qui peut en contenir 100.00
La voiture immatriculée 655CDE75 a 27341.00 kilomètres au compteur et 9.00 litres d'essence dans son réservoir, qui peut en contenir 40.00
La voiture immatriculée 654CDE75 a 25354.00 kilomètres au compteur et 7.00 litres d'essence dans son réservoir, qui peut en contenir 40.00
La voiture immatriculée 1234AA75 a 326671.00 kilomètres au compteur et 35.00 litres d'essence dans son réservoir, qui peut en contenir 100.00
TD : compte en banque
Compléter le programme :
type compte=record
nom:string[30]; // du titulaire du compte
solde:longint; // en euros
end;
procedure ...
var dup,dur:compte;
begin
dup.nom:='Jean Dupont';
dup.solde:=3000;
dur.nom:='Jacques Durand';
dur.solde:=-244;
crediter(dup,325);
crediter(dur,1287);
debiter(dup,23);
debiter(dup,423);
crediter(dur,43);
virer(dup,dur,127);
afficher(dup);
afficher(dur)
end.
retour sur les rationnels
Ecrire un programme qui calcule : ∑j=121232 1/(j2+j).
Il doit trouver 112/28193.
Ecrire un programme qui calcule : ∏j=100200 (j+1)/(j-2).
Il doit trouver 13333/1617.
Ecrire un programme qui calcule :
(∑i=1100 (i2+i+5)/pgcd(i+10,9000))/
(∑i=1100 (i2-i+5)/pgcd(i+10,9000))
suivant précédent sommaire
mercredi 23 février 2005 : tableaux : vecteurs
var r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12,
s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12:integer;
begin
write('Donnez les recettes des 12 mois : ');
readln(r1,r2,r3,r4,r5,r6,r7,r8,r9,r10,r11,r12);
write('Donnez les dépenses des 12 mois : ');
readln(s1,s2,s3,s4,s5,s6,s7,s8,s9,s10,s11,s12);
writeln(r1:8,'-',s1:8,'=',r1-s1:8);
writeln(r2:8,'-',s2:8,'=',r2-s2:8);
writeln(r3:8,'-',s3:8,'=',r3-s3:8);
writeln(r4:8,'-',s4:8,'=',r4-s4:8);
writeln(r5:8,'-',s5:8,'=',r5-s5:8);
writeln(r6:8,'-',s6:8,'=',r6-s6:8);
writeln(r7:8,'-',s7:8,'=',r7-s7:8);
writeln(r8:8,'-',s8:8,'=',r8-s8:8);
writeln(r9:8,'-',s9:8,'=',r9-s9:8);
writeln(r10:8,'-',s10:8,'=',r10-s10:8);
writeln(r11:8,'-',s11:8,'=',r11-s11:8);
writeln(r12:8,'-',s12:8,'=',r12-s12:8);
readln
end.
Le programme précédent peut s'écrire de façon plus concise avec des tableaux :
var r,s:array[1..12] of integer;
j:integer;
begin
write('Donnez les recettes des 12 mois : ');
for j:=1 to 12 do read(r[j]);
readln;
write('Donnez les dépenses des 12 mois : ');
for j:=1 to 12 do read(s[j]);
readln;
for j:=1 to 12 do writeln(r[j]:8,'-',s[j]:8,'=',r[j]-s[j]:8);
readln
end.
On peut utiliser les tableaux pour traiter des vecteurs.
const dim=3;
type real=extended;
vec=array[1..3] of real;
procedure addv(a,b:vec;var c:vec); // c:=a+b
var j:integer;
begin
for j:=1 to dim do c[j]:=a[j]+b[j]
end;
procedure souv(a,b:vec;var c:vec); // c:=a-b
var j:integer;
begin
for j:=1 to dim do c[j]:=a[j]-b[j]
end;
procedure litv(var a:vec); // readln(a)
var j:integer;
begin
write('Donnez ',dim,' nombres : ');
for j:=1 to dim do read(a[j]);
readln
end;
procedure ecritv(a:vec); // writeln(a)
var j:integer;
begin
for j:=1 to dim do write(a[j]:15:3);
writeln
end;
var a,b,c,d:vec;
begin
litv(a);
litv(b);
addv(a,a,c); // c:=2a
addv(c,c,d); // d:=4a
souv(a,d,c); // c:=-3a
addv(c,b,d); // d:=b-3a
ecritv(c);
ecritv(d);
readln
end.
TD :
somme, maximum et minimum
Modifier le programme vu en cours traitant des recettes et des dépenses, pour
qu'il calcule et affiche aussi les 9 nombres :
∑i=1nr[i],
∑i=1ns[i],
∑i=1nr[i]-t[i],
mini=1nr[i],
mini=1ns[i],
mini=1nr[i]-t[i],
maxi=1nr[i],
maxi=1ns[i] et
maxi=1nr[i]-t[i].
On pourra éventuellement écrire des procédures qui affichent la somme
ou le plus grand ou le petit des éléments d'un tableau de douze entiers.
On pourra aussi déclarer un troisième tableau t que l'on remplira avec t[i]=r[i]-s[i].
norme et produit scalaire de vecteurs
Ecrire un programme contenant les deux fonctions ayant pour entête
function normev(a:vec):real;
function prodscal(a,b:vec):real;
qui calculent la norme euclidienne d'un vecteur, √∑i=1na[i]2
et le produit scalaire de deux vecteurs ∑i=1na[i]b[i].
Le programme lira deux vecteurs et affichera leurs normes et leur produit scalaire.
tri d'un tableau d'entier
Ecrire un programme qui contienne
const n=10;
type tab=array[1..n] of integer;
function posmax(a:tab;k:integer):integer;
...
procedure tri(var a:tab);
...
posmax(a,k) doit être l'indice (et non pas la valeur) du plus grand parmi les k premiers
éléments de a.
Par exemple, si le plus grand des quatre nombres a[1], a[2], a[3] et a[4] est a[3], alors posmax(a,4) vaut 3.
La procédure tri(a) permute les éléments du tableau a, de manière à les mettre dans l'ordre croissant.
Elle utilisera l'algorithme suivant :
pour k=n, n-1, ... 1 faire
déterminer où se trouve le plus grand des k premiers éléments de a,
puis l'échanger avec a[k]
fait
Il y a donc une boucle for qui contient un appel à la fonction posmax.
suivant précédent sommaire
mercredi 9 mars 2005 : tableaux : matrices
Produit d'une matrice par un vecteur ou de deux matrices.
Lecture et écriture de matrices.
const dim=3;
type real=extended;
vec=array[1..3] of real;
mat=array[1..3] of vec;
procedure litv(var a:vec); // readln(a)
var j:integer;
begin
write('Donnez ',dim,' nombres : ');
for j:=1 to dim do read(a[j]);
readln
end;
procedure ecritv(a:vec); // writeln(a)
var j:integer;
begin
for j:=1 to dim do write(a[j]:15:3);
writeln
end;
procedure litm(var a:mat); // readln(a)
var j:integer;
begin
writeln('Entrez une matrice, ligne par ligne :');
for j:=1 to dim do litv(a[j])
end;
procedure ecritm(a:mat); // writeln(a)
var j:integer;
begin
writeln; // pour que la première ligne soit bien à gauche
for j:=1 to dim do ecritv(a[j]) // écrit la jème ligne
end;
procedure mulmvv(a:mat;b:vec;var c:vec); // c:=a*b
var s:real;
i,j:integer;
begin
for i:=1 to dim do
begin
s:=0;
for j:=1 to dim do s:=s+a[i,j]*b[j];
c[i]:=s
end
end;
procedure mulmmm(a,b:mat;var c:mat); // c:=a*b
var s:real;
i,j,k:integer;
begin
for i:=1 to dim do
for k:=1 to dim do
begin
s:=0;
for j:=1 to dim do s:=s+a[i,j]*b[j,k];
c[i,k]:=s
end
end;
var a,b,c:vec;
m1,m2,m3:mat;
begin
litv(a);
litm(m1);
litm(m2);
mulmvv(m1,a,b); // b:=m1*a
mulmvv(m2,b,c); // c:=m2*b
write('a='); ecritv(a);
write('m1='); ecritm(m1);
write('m2='); ecritm(m2);
write('m1 a='); ecritv(b);
write('m2 (m1 a)='); ecritv(c);
mulmmm(m2,m1,m3); // m3:=m2*m1
mulmvv(m3,a,c); // c:=m3*a
write('m2 m1='); ecritm(m3);
write('(m2 m1) a='); ecritv(c);
readln;
readln
end.
Le programme précédent écrit par exemple :
Donnez 3 nombres : 1 2 1
Entrez une matrice, ligne par ligne :
Donnez 3 nombres : 1 2 3
Donnez 3 nombres : 4 5 6
Donnez 3 nombres : 7 8 9
Entrez une matrice, ligne par ligne :
Donnez 3 nombres : 4 1 2
Donnez 3 nombres : 2 4 1
Donnez 3 nombres : 1 2 4
a= 1.000 2.000 1.000
m1=
1.000 2.000 3.000
4.000 5.000 6.000
7.000 8.000 9.000
m2=
4.000 1.000 2.000
2.000 4.000 1.000
1.000 2.000 4.000
m1 a= 8.000 20.000 32.000
m2 (m1 a)= 116.000 128.000 176.000
m2 m1=
22.000 29.000 36.000
25.000 32.000 39.000
37.000 44.000 51.000
(m2 m1) a= 116.000 128.000 176.000
TD :
transposée et trace
Ecrire un programme qui contienne des procédures calculant le produit de deux matrices et
la tranposée d'une matrice, et une fonction qui calcule la trace d'une matrice carrée.
Le programme principal doit calculer tr(A B C) et tr(B C A) et tr(tA tB tC) où
( 1 2 3 ) ( 9 8 7 ) ( 4 1 1 )
A = ( 4 5 6 ) B=( 6 5 4 ) C=( 1 4 1 )
( 7 8 9 ) ( 3 2 1 ) ( 1 1 4 )
suite de vecteurs
Soit H la matrice carrée 20x20, contenant les coefficients H[i,j]=1/(i+j-1).
On définit une suite de vecteurs qui a pour premier terme (1,1,...,1).
Après cela chaque terme se déduit du précédent en le multipliant par la
matrice H, puis en divisant le produit par sa première composante.
La suite de vecteurs ainsi obtenue converge.
Vous devez écrire un programme qui calcule sa limite.
On peut utiliser l'algorithme suivant
v:=(1,1,...,1)
répéter
u:=v
v:=H v
v:=v/v[1]
jusqu'à ce que u et v soient très proches
suivant précédent sommaire
mercredi 16 mars 2005 : tableaux
const n=10;
type tab=array[1..n] of integer;
procedure aff(a:tab);
var i:integer;
begin
for i:=1 to n do write(a[i]:5);
writeln
end;
procedure remplitaleat(var a:tab;min,max:integer);
var i:integer;
begin
for i:=1 to n do a[i]:=min+random(max-min+1)
end;
procedure addition(a,b:tab;var c:tab); // c:=a+b
var i:integer;
begin
for i:=1 to n do c[i]:=a[i]+b[i]
end;
procedure soustraction(a,b:tab;var c:tab); // c:=a-b
var i:integer;
begin
for i:=1 to n do c[i]:=a[i]-b[i]
end;
function somme(a:tab;n:integer):integer;
var s,i:integer;
begin
s:=0;
for i:=1 to n do s+=a[i];
somme:=s
end;
function produit(a:tab;n:integer):integer;
var s,i:integer;
begin
s:=1;
for i:=1 to n do s*=a[i];
produit:=s
end;
function max(a:tab;n:integer):integer;
var m,i:integer;
begin
m:=a[1];
for i:=2 to n do if a[i]>m then m:=a[i];
max:=m
end;
function min(a:tab;n:integer):integer;
var m,i:integer;
begin
m:=a[1];
for i:=2 to n do if a[i]a[p] then p:=i;
posmax:=p
end;
function posmin(a:tab;n:integer):integer;
var p,i:integer;
begin
p:=1;
for i:=2 to n do if a[i]1 do
begin
j:=posmax(a,n);
x:=a[j]; a[j]:=a[n]; a[n]:=x;
n:=n-1
end
end;
procedure tribulle(var a:tab;n:integer);
var k,kmax,x:integer;
begin
while n>1 do
begin
kmax:=1;
for k:=1 to n-1 do if a[k]>a[k+1] then
begin
x:=a[k]; a[k]:=a[k+1]; a[k+1]:=x;
kmax:=k
end;
n:=kmax
end
end;
var a,b,c,d:tab;
begin
remplitaleat(a,-4,6);
remplitaleat(b,-7,9);
addition(a,b,c);
soustraction(a,b,d);
aff(a);
writeln('Le plus grand est ',max(a,n),' Il est en position ',posmax(a,n));
writeln('Le plus petit est ',min(a,n),' Il est en position ',posmin(a,n));
writeln('La somme est ',somme(a,n));
writeln('Le produit est ',produit(a,n));
aff(b);
aff(c);
aff(d);
triselection(c,n);
tribulle(d,n);
aff(c);
aff(d)
end.
Le programme précédent écrit
3 1 -4 4 0 -3 6 4 5 2
Le plus grand est 6 Il est en position 7
Le plus petit est -4 Il est en position 3
La somme est 18
Le produit est 0
5 1 4 -5 -1 -2 3 -6 1 9
8 2 0 -1 -1 -5 9 -2 6 11
-2 0 -8 9 1 -1 3 10 4 -7
-5 -2 -1 -1 0 2 6 8 9 11
-8 -7 -2 -1 0 1 3 4 9 10
TD :
procedure stath(a:tab);
begin
end;
function nbcommuns(a,b:tab):integer;
begin
end;
var a,b:tab;
begin
remplitaleat(a,5,10);
remplitaleat(b,7,12);
aff(a);
stath(a);
aff(b);
writeln('il y a ',nbcommuns(a,b),' éléments communs.')
end.
Compléter le programme précédent pour qu'il affiche par exemple
9 8 5 9 7 5 10 9 9 8
2x5
1x7
2x8
4x9
1x10
11 9 11 7 9 9 10 7 9 12
il y a 6 éléments communs.
Il y a un 7, quatre 9 et un 10, ce qui fait bien six éléments communs.
suivant précédent sommaire
mercredi 23 mars 2005 : fichiers text
Un programme peut écrire ou lire des données dans un fichier sur le disque dur
ou une disquette ou une clef USB.
En fait tous les programmes écrits en pascal depuis le début de l'année utilisent des fichiers,
car le pascal considère l'écran comme un fichier dans lequel on écrit, et le clavier comme
un fichier dans lequel on lit.
Par exemple le programme
var j:integer;
begin
write('Donnez un nombre : ');
readln(j);
writeln(j,'+',j,'=',j+j);
readln
end.
utilise implicitement le fichier prédéfini OUTPUT qui correspond à l'écriture sur l'écran
ainsi que le fichier prédéfini INPUT qui correspond à la lecture au clavier.
On aurait pu l'écrire en utilisant explicitement les fichiers OUTPUT et INPUT :
var j:integer;
begin
write(output,'Donnez un nombre : ');
readln(input,j);
writeln(output,j,'+',j,'=',j+j);
readln(input)
end.
Le programme précédent est aussi équivalent au programme suivant, où on n'utilise pas
les fichiers prédéfinis OUTPUT et INPUT, mais on les redéfinit.
De plus on a étendu les instructions write, writeln et readln.
var j:integer;
output,input:text;
begin
assign(output,'con'); // 'con' veut dire console
assign(input,'con');
rewrite(output);
reset(input);
write(output,'Donnez un nombre : ');
read(input,j); readln(input);
write(output,j); write(output,'+'); write(output,j); write(output,'=');
write(output,j+j); writeln(output);
readln(input);
close(input);
close(output)
end.
Voici un exemple de programme qui écrit un vrai fichier sur le disque dur.
var f:text;
begin
assign(f,'c:\dev-pas\dupont\pi.txt');
rewrite(f);
writeln(f,'Que j''aime à faire connaître un nombre utile aux sages !');
writeln(f,'Immortel Archimède, artiste ingénieur,');
writeln(f,'qui de ton jugement peut priser la valeur ?');
writeln(f,'Pour moi, ton problème eut de pareils avantages.');
close(f);
readln
end.
Voici un autre programme qui lit le fichier créé précédemment et l'affiche sur l'écran.
var f:text;
c:char;
begin
assign(f,'c:\dev-pas\dupont\pi.txt');
reset(f);
while not eof(f) do
if eoln(f) then
begin
readln(f);
writeln
end else
begin
read(f,c);
write(c)
end;
close(f);
readln
end.
Lorsque l'on veut utiliser un fichier il faut appeler dans l'ordre :
la procédure assign
procedure assign(var f:text;nom:string);
pour dire sur quel support (a: pour une disquette, c: pour le disque dur, e: pour
une clef USB, con pour la console), dans quel répertoire et sous quel nom se trouvera
le fichier f.
une des trois procédures d'ouverture de fichier
procedure rewrite(var f:text);
pour écrire un nouveau fichier (Il est d'abord détruit s'il existait déjà).
procedure append(var f:text);
pour écrire à la suite d'un fichier existant déjà.
procedure reset(var f:text);
pour lire un fichier existant déjà à partir du début.
les procédures read, write, readln et writeln
On peut les utiliser autant qu'on veut tant que le fichier est ouvert.
On peut utiliser read et readln sur un fichier ouvert en lecture par reset.
On peut utiliser write et writeln sur un fichier ouvert en écriture par rewrite ou append.
Sur un fichier ouvert en lecture, on peut aussi utiliser les deux fonctions booléennes
eof et eoln.
eof(f) est vrai si on est à la fin (End Of File) du fichier f,
et qu'il n'y a donc plus rien à lire dedans.
eoln(f) est vrai si on est à la fin d'une ligne (End Of LiNe) dans le fichier f,
et qu'il n'y a donc plus rien à lire avant le passage à la ligne.
la procédure de fermeture
close(f) permet de fermer le fichier f quand on n'a plus rien à lire ou à écrire dedans.
Lorsque l'on veut être sûr que les données sont bien écrites sur le disque et ne restent
pas en attente dans un tampon en mémoire, on peut appeler close(f) suivi immédiatement
par append(f) si on veut continuer à écrire dans le fichier.
On peut aussi remplacer ces deux appels par un seul appel : flush(f), qui s'assure que
toutes les données qui sont encore dans le tampon de f sont bien écrites dans f, en
gardant f ouvert.
TD :
Ecrire le programme vu en cours qui lit le fichier pi.txt et l'affiche sur l'écran.
Ecrire un programme qui affiche la suite des longueurs des mots du fichier pi.txt.
Ecrire un programme qui demande un nom de fichier puis affiche le nombre de 'e' dans
ce fichier.
Ecrire un programme qui demande un nom de fichier existant et un nom de fichier à créer,
et qui met dans le deuxième fichier, une copie du premier dans laquelle on a enlevé
tous les blancs qui suivent un autre blanc, autrement dit, les groupes de plusieurs
blancs consécutifs sont remplacés par un seul blanc.
suivant précédent sommaire
mercredi 30 mars 2005 : fichiers binaires
write et writeln
write et writeln peuvent avoir un nombre quelconque d'arguments mais on peut toujours
se ramener à au cas où write a deux arguments : un premier de type text et un second de type
caractère, chaîne de caractères, entier, réel ou booléen et où writeln a un seul argument
de type text. Pour cela il suffit d'appliquer les trois règles suivantes :
1) Si le premier argument n'est pas un fichier, alors tout se passe comme si on avait
ajouté output comme argument supplémentaire en tête.
Par exemple writeln('i=',i) est équivalent à writeln(output,'i=',i)
2) Un writeln avec plusieurs arguments est équivalent à un write avec les mêmes arguments
suivi d'un writeln appliqué seulement au fichier.
Par exemple writeln(output,'i=',i) est équivalent à
begin write(output,'i=',i); writeln(output) end
3) Un write avec plus de deux arguments revient à écrire dans le même fichier, qui est le
premier argument, successivement, dans l'ordre chacun des autres arguments.
Par exemple write(output,'i=',i) est équivalent à
begin write(output,'i='); write(output,i) end
En appliquant ces trois règles on obtient par exemple que
writeln('i=',i) est équivalent à
begin write(output,'i='); write(output,i); writeln(output) end
Le deuxième argument d'un write peut être un caractère, une chaîne de caractères, un entier,
un réel ou un booléen.
On peut préciser sur combien de caractères il doit être écrit.
Cela rajoute éventuellement des blancs à gauche.
Par exemple, sur chaque ligne qui suit, les deux instructions sont équivalentes.
write(f,34) write(f,'34')
write(f,34:4) write(f,' 34')
write(f,'ab':4) write(f,' ab')
write(f,3=3) write(f,'TRUE')
write(f,3=3:2) write(f,'TRUE')
write(f,3=4:8) write(f,' FALSE')
writeln(f,3.4) write(f,' 3.4000000000000000E+0000')
writeln(f,3.4:6) write(f,' 3.4E+0000')
writeln(f,3.4:6:2) write(f,' 3.40')
writeln(f,3.4:6:0) write(f,' 3')
Pour les réels, on peut préciser aussi le nombre de chiffres après le point que l'on veut
écrire.
Dans ce cas on n'utilise pas la notation exponentielle E+0003.
Si on demande zéro chiffre décimal, le point n'est pas écrit.
writeln(f) écrit un passage à la ligne dans le fichier.
Un fichier text peut être considéré comme une suite de caractères et de passages à ligne.
Une ligne est l'ensemble des caractères se trouvant entre deux passages à la ligne.
Une ligne vide correspond à deux passages à la lignes qui se suivent directement
sans aucun caractère entre eux.
read et readln
read et readln peuvent avoir un nombre quelconque d'arguments mais on peut toujours
se ramener à au cas où read a deux arguments : un premier de type text et un second de type
caractère, chaîne de caractères, entier, réel ou booléen et où readln a un seul argument
de type text. Pour cela il suffit d'appliquer les trois règles suivantes :
1) Si le premier argument n'est pas un fichier, alors tout se passe comme si on avait
ajouté input comme argument supplémentaire en tête.
Par exemple readln(j,i) est équivalent à readln(input,j,i)
2) Un readln avec plusieurs arguments est équivalent à un read avec les mêmes arguments
suivi d'un readln appliqué seulement au fichier.
Par exemple readln(input,j,i) est équivalent à
begin read(input,j,i); readln(input) end
3) Un read avec plus de deux arguments revient à lire dans le même fichier, qui est le
premier argument, successivement, dans l'ordre chacun des autres arguments.
Par exemple read(input,j,i) est équivalent à
begin read(input,j); read(input,i) end
En appliquant ces trois règles on obtient par exemple que
readln(j,i) est équivalent à
begin read(input,j); read(input,i); readln(input) end
read appliqué à une variable de type caractère lit un caractère.
On ne doit pas le faire quand on est en fin de ligne, c'est-à-dire si la prochaine
chose à lire est un passage à la ligne.
read appliqué à une chaine de charactères lit autant de caractères que possible,
c'est-à-dire jusqu'à la fin de la ligne où j'usqu'à ce que la chaîne de caractères ait
sa longueur maximale. On ne change jamais de ligne (on ne mange jamais de passage à la ligne).
readln mange le prochain passage à la ligne ainsi que tous les caractères qui le précèdent.
Il fait donc passer au début de la ligne suivante en ignorant la fin la ligne courante.
La lecture d'un nombre (entier ou réel) se fait en ignorant d'abord tous les blancs et
les passages à la ligne qui précèdent ce nombre. Après le nombre il doit y avoir
un blanc qui est mangé ou un passage à la ligne qui est laissé.
Par exemple si on a déclaré
var s,t:string[4];
c,d:char;
i,j:integer;
et que f correspond à un fichier contenant
abcdef<cr>
<cr>
12 3456<cr>
ghi<cr>
klmnopqrstuvwx<cr>
<cr>
7 8 9<cr>
Les instructions
readln(f,s,t,i,c,d,j);
readln(s,t);
readln(s,t);
read(i,c,d,j)
sont équivalentes à
s:='abcd'; t:='ef'; i:=12; c:='3'; d:='4'; j:=56;
s:='ghi'; t:='';
s:='klmn'; t:='opqr';
i:=7; c:='8'; d:=' '; j:=9
fichiers binaires
var f:file of integer;
j:integer;
begin
assign(f,'10a1');
rewrite(f);
for j:=10 downto 1 do write(f,j);
close(f)
end.
var g:file of integer;
j:integer;
begin
assign(g,'10a1');
reset(g);
while not eof(g) do
begin
read(g,j);
write(j:5)
end;
readln
end.
TD :
exercice 1
Ecrire un programme qui crée un fichier d'entiers dont on demande à l'utilisateur
le nom puis le contenu.
L'exécution pourra ressembler à
Nom du fichier d'entiers à créer : truc
Contenu du fichier : 10 20 13 2 4
5 -8 -9 10 40 a
On pourra utiliser une boucle infinie, comme repeat ... until false, pour
remplir le fichier. On sortira de cette boucle en tapant une lettre au lieu d'un chiffre.
Cela provoque une erreur d'entrée-sortie qui normalement arrête l'exécution du programme,
mais que l'on peut récupérer en remplaçant read(j) par
(*$i-*)
read(j);
if ioresult<>0 then break
(*$i+*)
ioresult est une fonction qui rend 0 si la dernière entrée-sortie s'est effectuée sans erreur,
et sinon un nombre qui indique quelle erreur a eu lieu.
break fait sortir d'une boucle for ou repeat.
(*$i-*) et (*$i+*) sont des faux commentaires car ils commencent par un dollar.
(*$i+*) indique que dans ce qui suit, toute instruction d'entrée-sortie qui se passe mal
provoque l'arrêt immédiat du programme.
(*$i-*) indique que dans ce qui suit, une instruction d'entrée-sortie qui se passe mal
ne provoquera l'arrêt du programme que si on essaye d'exécuter une autre instruction
d'entrée-sortie sans avoir entre temps appelé la fonction ioresult.
exercice 2
Ecrire un programme qui demande à l'utilisateur un nom de fichier d'entiers et qui
affiche son contenu à l'écran.
exercice 3
Ecrire un programme qui demande à l'utilisateur un nom de fichier d'entiers et ajoute 1
à chacun de ses éléments.
exercice 4
Ecrire un programme qui échange le plus petit et le plus grand des éléments
d'un fichier d'entiers
exercice 5
Ecrire un programme qui trie dans l'ordre croissant les éléments d'un fichier d'entiers
suivant précédent sommaire
mercredi 6 avril 2005 : fichiers
lecture d'un fichier binaire à l'envers
var f:file of integer;
j,k:integer;
begin
assign(f,'truc');
reset(f);
for j:=filesize(f)-1 downto 0 do
begin
seek(f,j);
read(f,k);
write(k,' ')
end;
close(f)
end.
var f:file of integer;
k:integer;
begin
assign(f,'truc');
append(f);
while not eof(f) do
begin
seek(f,filepos(f)-1):
read(f,k);
seek(f,filepos(f)-1):
write(k,' ')
end;
close(f)
end.
modification de fichiers, mélange de read et de write
var f:file of integer;
j:integer;
begin
assign(f,'truc');
reset(f);
while not eof(f) do
begin
read(f,j);
write(f,j)
end;
close(f)
end.
Ce programme duplique un élément sur deux.
Par exemple si le fichier contenait
23 4 56 32 7 avant l'exécution du programme, son contenu devient 23 23 56 56 7 7.
Le premier write a remplacé 4 par 23, le second a remplacé 32 par 56 et le troisième a créé
un nouvel enregistrement à la fin du fichier contenant 7.
var f:file of integer;
j:integer;
begin
assign(f,'truc');
append(f);
while filepos(f)>2 do
begin
seek(f,filepos(f)-3);
read(f,j);
write(f,j)
end;
close(f)
end.
Si par exemple le fichier contenait
23 4 56 32 7 avant l'exécution du programme, son contenu devient 23 23 4 56 7.
A la première itération de la boucle, 32 est remplacé par 56.
A la deuxième le premier 56 est remplacé par 4.
A la deuxième le premier 4 est remplacé par 23.
la fonction readkey
La fonction readkey rend le prochain caractère tapé au clavier.
Ce caractère n'est pas affiché sur l'écran et il n'a pas besoin d'être validé
par la touche entrée.
On n'a donc pas droit à l'erreur : On ne peut pas le supprimer en tapant la touche
backspace, comme avec read(input, ...) .
Cette fonction se trouve dans l'unité crt.
uses crt;
var c:char;
begin
repeat
c:=readkey;
writeln(ord(c))
until (c='q') or (c='Q') or (c=#3)
end.
Le programme précédent lit un caractère au clavier et affiche son code ascii à l'écran,
puis recommence jusqu'à ce que l'on tape Q ou <ctrl>C.
A donne 65, B donne 66, C donne 67, ..., Z donne 90, a donne 97, b donne 98, c donne 99, ...,
z donne 122, + donne 43, - donne 45, l'espace donne 32.
Ce programme permet donc de connaître les codes ascii de certains caractères, mais il permet
surtout de savoir quels caractères donnent les touches spéciales du clavier.
Par exemple la touche backspace donne le caractère de code ascii 8, noté #8 en pascal.
Les touches de déplacement du curseur donnent deux caractères #0 et un autre :
à droite #0 #77, à gauche #0 #75, en haut #0 #72, en bas #0 #80.
La touche insertion donne #0 #82.
La touche suppression donne #0 #83.
La touche échapement donne #27.
<ctrl>A donne #1,
<ctrl>B donne #2,
<ctrl>C donne #3, etc..
TD :
exercice 1
Ecrire un programme appelé sommefic.pas qui lit deux fichiers d'entiers et en crée un troisième
qui contient la somme des premiers éléments, puis la somme des seconds éléments etc..
Il devra d'abord demander le nom des trois fichiers.
truc : 7 3 5 ...
machin : 8 4 3 ...
->
bidule : 15 7 8 ...
exercice 2
Ecrire un programme appelé doubledemific.pas qui modifie un fichier d'entiers.
Chaque nombre pair est remplacé par sa moitié et chaque nombre impair par son double.
Il devra d'abord demander le nom du fichier.
truc : 20 10 7 3 5 8
->
truc : 10 5 14 6 10 4
exercice 3
Ecrire un programme appelé concatfic.pas qui lit deux fichiers d'entiers et en crée un troisième
qui contient les deux premiers mis bout à bout.
Il devra d'abord demander le nom des trois fichiers.
truc : 3 4 7
machin : 6 4 2 8
->
bidule : 3 4 7 6 4 2 8
suivant précédent sommaire
mercredi 13 avril 2005 : système d'équations linéaires
On veut résoudre le système d'équations linéaires suivant par la méthode du pivot de Gauss.
2x+4y+z=5
3x+9y+z=6
x+ y+z=3
Dans la première colonne, parmi 3, 3 et 1, le coefficient ayant la plus grande
valeur absolue est 3. Il se trouve sur la deuxième ligne.
On échange donc les deux premières équations pour amener le 3 (le pivot) en haut à gauche.
3x+9y+z=6
2x+4y+z=5
x+ y+z=3
On divise la première équation par 3, pour remplacer le pivot par 1.
x+3y+(1/3)z=2
2x+4y+ z=5
x+ y+ z=3
On soustrait le double de la première équation à la seconde pour en éliminer les x.
Eq2:=Eq2-2Eq1
On soustrait la première équation à la troisième pour en éliminer les x.
Eq3:=Eq3-Eq1
x+3y+(1/3)z=2
-2y+(1/3)z=1
-2y+(2/3)z=1
On recommence les opérations précédentes avec le système des deux dernières équations.
-2 et -2 ont la même valeur absolue.
On n'a donc pas besoin d'échanger les deux dernières équations.
On divise l'équation 2 par -2.
x+3y+(1/3)z=2
y-(1/6)z=-1/2
-2y+(2/3)z=3
On ajoute le double de la deuxième équation à la troisième pour en éliminer y.
x+3y+(1/3)z=2
y-(1/6)z=-1/2
-(1/3)z=0
On divise la troisième équation par -1/3.
x+3y+(1/3)z=2
y-(1/6)z=-1/2
z=0
On a maintenant un système triangulaire supérieur, avec des 1 sur la diagonale.
On peut le résoudre en calculant d'abord z, puis y et enfin x.
z=0
y=-1/2+(1/6)z=-1/2+(1/6)0=-1/2
x=2-3y-(1/3)z=2-3(-1/2)-(1/3)0=7/2
On a utilisé l'algorithme suivant, écrit en pseudo-pascal
for m:=1 to 3 do
begin
Dans la colonne M dans les lignes M à 3, on cherche
le coefficient ayant la plus grande valeur absolue.
Soit J le numéro de sa ligne.
On échange les équations J et M.
Eqm:=Eqm/a[m,m]
for j:=m+1 to 3 do
begin
Eqj:=Eqj-a[m,j]Eqm
end
end
for j:=3 downto 1 do
begin
x[j]:=b[j]-∑k=j+1dima[j,k] x[k]
end
En pascal cela donne :
procedure resoutgauss(a:mat;b:vec;var x:vec); (* A X=B *)
var m,j,k:integer;
l:vec;
p,s:real;
begin
for m:=1 to dim do
begin
(* On met dans J le numéro de la ligne où se trouve le plus grand
en valeur absolue parmi les nombres situé dans la colonne M sur la diagonale
et en dessous.
abs(a[j,m])=maxm≤k≤dimabs a[k,m] *)
j:=m;
for k:=m+1 to dim do if abs(a[k,m])>abs(a[j,m]) then j:=k;
(* On échange les équations J et M pour amener ce grand coefficient
sur la diagonale. On l'appellera le pivot. *)
l:=a[j]; a[j]:=a[m]; a[m]:=l;
s:=b[j]; b[j]:=b[m]; b[m]:=s;
(* On divise la ligne du pivot par le pivot.
eqm:=eqm/a[m,m] *)
p:=a[m,m]; (* ancienne valeur du pivot (a[m,m] va devenir 1) *)
for k:=m to dim do a[m,k]/=p;
b[m]/=p;
for j:=m+1 to dim do (* pour chaque ligne J en dessous du pivot *)
begin
(* On soustrait un multiple de la ligne du pivot à la ligne J de façon à faire
apparaître un 0 dans la colonne du pivot.
eqj:=eqj-a[j,m]*eqm *)
p:=a[j,m]; (* ancienne valeur de a[j,m]. La nouvelle valeur est 0 *)
for k:=m to dim do a[j,k]-=p*a[m,k];
b[j]-=p*b[m]
end
end;
(* Le système est maintenant triangulaire supérieur avec des 1 sur la diagonale.
Il faut maintenant résoudre ce système. *)
for j:=dim downto 1 do
begin
(* La ligne J du système A X=B est
∑k=1dima[j,k] x[k]=b[j]
Puisque A est triangulaire supérieure, a[j,k] est nul si k>j et vaut 1 si k=j. Donc :
x[j]+∑k=j+1dima[j,k] x[k]=b[j]
On peut donc calculer :
x[j]:=b[j]-∑k=j+1dima[j,k] x[k]
On calculera donc dans l'ordre
x[dim ]:=b[dim]
x[dim-1]:=b[dim-1]-a[dim-1,dim]*x[dim]
x[dim-2]:=b[dim-2]-a[dim-2,dim]*x[dim]-a[dim-2,dim-1]*x[dim-1]
... *)
s:=b[j];
for k:=j+1 to dim do s-=a[j,k]*b[k];
x[j]:=s
end
end;
TD :
exercice 1
Intégrer la procédure vue en cours dans un programme qui résout le système vu en exemple
en cours.
exercice 2
Si trois matrices vérifient A B=C alors A Bi=Ci où Bi et Ci représentent les ièmes colonnes
de B et C.
Utiliser cette propriété pour calculer l'inverse d'une matrice A colonne par colonne, en
résolvant tous les sytèmes d'équations linéaires ayant pour matrice A et pour membre droit
une colonne de la matrice identité.
suivant précédent sommaire
mercredi 20 avril 2005 : polynômes
const dmax=30;
type real=extended;
poly=array[0..dmax] of real;
procedure litpoly(var a:poly);
var j:integer;
begin
for j:=0 to dmax do a[j]:=0;
for j:=0 to dmax do
begin
(*$i-*)
read(a[j]);
(*$i+*)
if ioresult<>0 then exit
end
end;
procedure ecritpoly(a:poly);
var j:integer;
nul:boolean;
x:real;
begin
nul:=true;
for j:=0 to dmax do if a[j]<>0 then
begin
if a[j]<0 then write('-') else
if not nul then write('+');
nul:=false;
x:=abs(a[j]);
if x=int(x) then if (x<>1) or (j=0) then write(x:0:0)
else
else write(x:0:4);
case j of
0:;
1:write('X');
//2:write('X²');
else write('X^',j)
end
end;
if nul then write(0)
end;
procedure addpol(a,b:poly;var c:poly); // c:=a+b
var j:integer;
begin
for j:=0 to dmax do c[j]:=a[j]+b[j]
end;
procedure subdpol(a,b:poly;var c:poly); // c:=a-b
var j:integer;
begin
for j:=0 to dmax do c[j]:=a[j]-b[j]
end;
function degre(a:poly):integer;
var j:integer;
begin
degre:=-1;
for j:=0 to dmax do if a[j]<>0 then degre:=j
end;
procedure mulpol(a,b:poly;var c:poly); // c:=a*b
var da,db,j,k:integer;
begin
da:=degre(a);
db:=degre(b);
if da+db>dmax then
begin
write('Le produit de '); ecritpoly(a); write(' et de ');
ecritpoly(b); writeln(' a un degre trop eleve.');
halt
end;
for j:=0 to dmax do c[j]:=0;
for j:=0 to da do if a[j]<>0 then
for k:=0 to db do c[j+k]+=a[j]*b[k]
end;
function valpol(a:poly;x:real):real;
var v:real;
j:integer;
begin
v:=0;
for j:=dmax downto 0 do v:=v*x+a[j];
valpol:=v
end;
procedure derpol(a:poly;var b:poly); // b:=a'
var j:integer;
begin
for j:=1 to dmax do b[j-1]:=j*a[j];
b[dmax]:=0
end;
TD :
Avec les procédures vues en cours, écrire un programme qui calcule
les deux polynômes
∏i=14(1-Xi) et
∏i=14(X2+i X-1).
var a,b:poly;
j:integer;
begin
for j:=0 to dmax do a[j]:=0;
a[0]:=1;
b:=a;
for j:=1 to 4 do
begin
b[j]:=-1;
mulpol(a,b,a);
b[j]:=0
end;
ecritpoly(a); writeln;// ∏i=14(1-Xi)
for j:=0 to dmax do a[j]:=0;
a[0]:=1;
b:=a;
b[0]:=-1;
b[2]:=1;
for j:=1 to 4 do
begin
b[1]:=j;
mulpol(a,b,a)
end;
ecritpoly(a); writeln;// ∏i=14(X2+i X-1)
readln
end.
Ce programme écrit :
1-X-X^2+2X^5-X^8-X^9+X^10
1-10X+31X^2-20X^3-40X^4+20X^5+31X^6+10X^7+X^8
suivant précédent sommaire
mercredi 11 mai 2005 : tableaux à deux dimensions
type tab=array[1..6,1..6] of integer;
procedure affdiag1(a:tab);
var j:integer;
begin
for j:=1 to 6 do write(a[j,j])
end;
procedure affdiag2(a:tab);
var j:integer;
begin
for j:=1 to 6 do write(a[j,7-j])
end;
procedure aff1(a:tab);
var j,k:integer;
begin
for j:=1 to 6 do
for k:=1 to 6 do write(a[j,k])
end;
procedure aff2(a:tab);
var j,k:integer;
begin
for j:=1 to 6 do
for k:=1 to 6 do write(a[j,k]:3)
end;
procedure aff3(a:tab);
var j,k:integer;
begin
for j:=1 to 6 do
for k:=1 to 6 do writeln(a[j,k]:3)
end;
procedure affmat(a:tab);
var j,k:integer;
begin
for j:=1 to 6 do
begin
for k:=1 to 6 do write(a[j,k]:3);
writeln
end
end;
procedure affmat2(a:tab);
var j,k:integer;
begin
writeln;
for j:=1 to 6 do
begin
for k:=1 to 6 do write(a[j,k]:3);
writeln
end
end;
procedure affmat3(a:tab);
var j,k:integer;
begin
writeln;
for j:=6 downto 1 do
begin
for k:=1 to 6 do write(a[k,j]:3);
writeln
end
end;
procedure transpose(a:tab;var b:tab);
var x,y:integer;
begin
for x:=1 to 6 do
for y:=1 to 6 do b[x,y]:=a[y,x]
end;
procedure miroirhorizontal(a:tab;var b:tab);
var x,y:integer;
begin
for x:=1 to 6 do
for y:=1 to 6 do b[x,y]:=a[7-x,y]
end;
procedure miroirhorizontalfaux(var a:tab;var b:tab);
var x,y:integer;
begin
for x:=1 to 6 do
for y:=1 to 6 do b[x,y]:=a[7-x,y]
end;
procedure miroirvertical1(a:tab;var b:tab);
var x,y:integer;
begin
for x:=1 to 6 do
for y:=1 to 6 do b[x,y]:=a[x,7-y]
end;
procedure miroirvertical2(a:tab;var b:tab);
begin
transpose(a,b);
miroirhorizontal(b,b);
transpose(b,b)
end;
var a,b:tab;
j,k:integer;
begin
for j:=1 to 6 do
for k:=1 to 6 do a[j,k]:=10*j+k;
affdiag1(a); affdiag2(a); aff1(a); aff2(a);
write('matrice A : '); aff3(a);
write('matrice A : '); affmat(a);
write('matrice A : '); affmat2(a);
write('matrice A : '); affmat3(a);
transpose(a,b); affmat2(b);
miroirhorizontal(a,b); affmat2(b);
miroirvertical1(a,b); affmat2(b);
miroirvertical2(a,b); affmat2(b);
miroirhorizontalfaux(a,a); affmat2(a);
readln
end.
Ce programme écrit :
112233445566162534435261111213141516212223242526313233343536414243444546515253545556616263646566 11 12 13 14 15 16 21 22 23 24 25 26 31 32 33 34 35 36 41 42 43 44 45 46 51 52 53 54 55 56 61 62 63 64 65 66matrice A : 11
12
13
14
15
16
21
22
23
24
25
26
31
32
33
34
35
36
41
42
43
44
45
46
51
52
53
54
55
56
61
62
63
64
65
66
matrice A : 11 12 13 14 15 16
21 22 23 24 25 26
31 32 33 34 35 36
41 42 43 44 45 46
51 52 53 54 55 56
61 62 63 64 65 66
matrice A :
11 12 13 14 15 16
21 22 23 24 25 26
31 32 33 34 35 36
41 42 43 44 45 46
51 52 53 54 55 56
61 62 63 64 65 66
matrice A :
16 26 36 46 56 66
15 25 35 45 55 65
14 24 34 44 54 64
13 23 33 43 53 63
12 22 32 42 52 62
11 21 31 41 51 61
11 21 31 41 51 61
12 22 32 42 52 62
13 23 33 43 53 63
14 24 34 44 54 64
15 25 35 45 55 65
16 26 36 46 56 66
61 62 63 64 65 66
51 52 53 54 55 56
41 42 43 44 45 46
31 32 33 34 35 36
21 22 23 24 25 26
11 12 13 14 15 16
16 15 14 13 12 11
26 25 24 23 22 21
36 35 34 33 32 31
46 45 44 43 42 41
56 55 54 53 52 51
66 65 64 63 62 61
16 15 14 13 12 11
26 25 24 23 22 21
36 35 34 33 32 31
46 45 44 43 42 41
56 55 54 53 52 51
66 65 64 63 62 61
61 62 63 64 65 66
51 52 53 54 55 56
41 42 43 44 45 46
41 42 43 44 45 46
51 52 53 54 55 56
61 62 63 64 65 66
TD :
Ecrire un programme qui quand on l'exécute affiche par exemple :
taille du carré : 6
1 2 3 4 5 6
20 21 22 23 24 7
19 32 33 34 25 8
18 31 36 35 26 9
17 30 29 28 27 10
16 15 14 13 12 11
Corrigé :
const dim=20;
var a:array[1..dim,1..dim] of integer;
i,j,dx,dy,z,k,n:integer;
begin
write('Taille du carre : ');
readln(n);
for i:=1 to n do
for j:=1 to n do a[i,j]:=0;
i:=1;
j:=1;
dx:=0;
dy:=1;
for k:=1 to n*n do
begin
a[i,j]:=k;
if (i+dx>0) and (i+dx<=n) and
(j+dy>0) and (j+dy<=n) and (a[i+dx,j+dy]=0) then else
begin
z:=dx; dx:=dy; dy:=-z
end;
i+=dx;
j+=dy
end;
for i:=1 to n do
begin
for j:=1 to n do write(a[i,j]:4);
writeln
end;
readln
end.
suivant précédent sommaire
mercredi 18 mai 2005 : méthode de Newton
type real=extended;
function f(x:real):real;
begin
f:=sin(x)/cos(x)-x
end;
function fp(x:real):real;
begin
fp:=1/sqr(cos(x))
end;
function newton(x:real):real;
var y:real;
begin
repeat
y:=x;
x-=f(x)/fp(x)
until x=y;
newton:=x
end;
var i:integer;
x:real;
begin
for i:=1 to 10 do
begin
x:=newton((i+0.5)*3.14);
writeln(i:2,x:30:22,sin(x)/cos(x):30:22)
end
end.
Le programme précédent écrit :
1 4.49340945790906420 4.49340945790906420
2 7.72525183693770720 7.72525183693770720
3 10.90412165942890000 10.90412165942890000
4 14.06619391283147300 14.06619391283147400
5 17.22075527193076900 17.22075527193076900
6 20.37130295928756300 20.37130295928756300
7 23.51945249868900700 23.51945249868900700
8 26.66605425881267400 26.66605425881267400
9 29.81159879089295900 29.81159879089296000
10 32.95638903982247700 32.95638903982247700
const dmax=30;
type real=extended;
poly=array[0..dmax] of real;
function degre(a:poly):integer;
var j:integer;
begin
degre:=-1;
for j:=0 to dmax do if a[j]<>0 then degre:=j
end;
function valpol(a:poly;x:real):real;
var v:real;
j:integer;
begin
v:=0;
for j:=dmax downto 0 do v:=v*x+a[j];
valpol:=v
end;
procedure derpol(a:poly;var b:poly); // b:=a'
var j:integer;
begin
for j:=1 to dmax do b[j-1]:=j*a[j];
b[dmax]:=0
end;
function newtonpol(p:poly;x:real):real;
var dp:poly;
y,z:real;
begin
derpol(p,dp);
y:=x;
repeat
z:=y; y:=x;
x-=valpol(p,x)/valpol(dp,x)
until x=z;
newtonpol:=x
end;
function newtonpol2(p:poly;x:real):real;
var dp:poly;
y,z,px,dpx:real;
j,d:integer;
begin
d:=degre(p);
derpol(p,dp);
y:=x;
repeat
z:=y; y:=x;
px:=0;
dpx:=0;
for j:=d downto 0 do
begin
dpx:=dpx*x+dp[j];
px:= px*x+ p[j]
end;
x-=px/dpx
until x=z;
newtonpol2:=x
end;
function newtonpol3(p:poly;x:real):real;
var y,z,px,dpx:real;
j,d:integer;
begin
d:=degre(p);
y:=x;
repeat
z:=y; y:=x;
px:=0;
dpx:=0;
for j:=d downto 0 do
begin
dpx:=dpx*x+px;
px:= px*x+p[j]
end;
x-=px/dpx
until x=z;
newtonpol3:=x
end;
var a:poly;
i:integer;
begin
for i:=0 to dmax do a[i]:=0;
a[0]:=1;
a[2]:=-5;
a[4]:=1;
for i:=-3 to 3 do if odd(i) then
writeln(i:2,newtonpol(a,i):25:20,newtonpol2(a,i):25:20,newtonpol3(a,i):25:20)
end.
Le programme précédent écrit :
-3 -2.18890105931673390 -2.18890105931673390 -2.18890105931673390
-1 -0.45685025174785665 -0.45685025174785665 -0.45685025174785665
1 0.45685025174785665 0.45685025174785665 0.45685025174785665
3 2.18890105931673390 2.18890105931673390 2.18890105931673390
La procédure newtonpol utilise la fonction valpol qui fait une boucle de 30 à 0.
Les 26 premières itérations de cette boucle calculent 0*x+0=0.
La procédure newtonpol2 fait exactement les mêmes calculs sans faire ces 26 premières itérations
inutiles.
La procédure newtonpol3 fait à peu près les mêmes calculs que newtopol2, sans utiliser
la variable DP qui contenait le polynôme dérivé de P.
Sa boucle calcule :
dpx:=0
px :=0
dpx:=0*x+0=0
px :=0*x+a=a
dpx:=0*x+a=a
px :=a*x+b
dpx:=a*x+(a*x+b)=2*a*x+b
px :=(a*x+b)*x+c=a*x2+b*x+c
dpx:=(2*a*x+b)*x+(a*x2+b*x+c)=3*a*x2+2*b*x+c
px :=(a*x2+b*x+c)*x+d=a*x3+b*x2+c*x+d
On voit que l'expression de dpx est bien la dérivée par rapport à x de l'expression de dx.
suivant précédent sommaire
mercredi 25 mai 2005 : dichotomie
type real=extended;
fonc=function(a:real):real;
function newton(f,df:fonc;x:real):real;
var j,n:integer;
y:real;
begin
for j:=1 to 1000 do
begin
y:=x;
for n:=1 to 10 do
begin
x-=f(x)/df(x);
if x=y then begin newton:=x; exit end
end
end;
writeln('raté'); readln; halt
end;
function f1 (x:real):real;begin f1 :=sin(x)/cos(x)-x end;
function f1p(x:real):real;begin f1p:=1/sqr(cos(x))-1 end;
function f2 (x:real):real;begin f2 :=1/(1+x*x)-0.7 end;
function f2p(x:real):real;begin f2p:=-2*x/sqr(1+x*x) end;
function f3 (x:real):real;begin f3 :=x*x-3*x+2 end;
function f3p(x:real):real;begin f3p:=2*x-3 end;
function f4 (x:real):real;begin f4 :=x*ln(x) end;
function dichotomie(f:fonc;a,b:real):real;
var m,fa,fb:real;
begin
fa:=f(a);
fb:=f(b);
if fa=0 then dichotomie:=a else
if fb=0 then dichotomie:=b else
if (fa<0)=(fb<0) then begin write('raté');readln;halt end else
if fa>0 then dichotomie:=dichotomie(f,b,a) else
repeat
m:=(a+b)/2;
if (m=a) or (m=b) then begin dichotomie:=a; break end;
if f(m)<0 then a:=m
else b:=m
until false
end;
function minconv(f:fonc;a,b,c:real):real;
var m:real;
begin
repeat
if abs(a-b)>abs(b-c) then begin m:=a; a:=c; c:=m end;
m:=(2*b+c)/3;
if (m=b) or (m=c) then break;
if f(m)
Le programme précédent écrit :
4.49340945790906420 4.49340945790906420
0.65465367070797714 0.65465367070797714
2.00000000000000000 2.00000000000000000
1.49999999956980420 1.50000000000000000
0.36787944111355262 0.36787944117144232
précédent sommaire
TD : mercredi 1er juin 2005 : affichage de tableaux carrés
Ecrire un programme qui lit un nombre n puis affiche des tableaux carrés de tailles
n selon l'exemple suivant :
Donnez un nombre : 5
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 2 3 4 5
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
4 4 4 4 4
5 5 5 5 5
1 1 1 1 1
1 2 2 2 2
1 2 3 3 3
1 2 3 4 4
1 2 3 4 5
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
5 6 7 8 9
1 0 0 0 1
0 1 0 1 0
0 0 1 0 0
0 1 0 1 0
1 0 0 0 1
1 6 10 13 15
0 2 7 11 14
0 0 3 8 12
0 0 0 4 9
0 0 0 0 5
2 1 0 0 1 2 1 0 0 1 2 (si n=11)
1 2 1 0 1 2 1 0 1 2 1
0 1 2 1 1 2 1 1 2 1 0
0 0 1 2 1 2 1 2 1 0 0
1 1 1 1 2 2 2 1 1 1 1
2 2 2 2 2 2 2 2 2 2 2
1 1 1 1 2 2 2 1 1 1 1
0 0 1 2 1 2 1 2 1 0 0
0 1 2 1 1 2 1 1 2 1 0
1 2 1 0 1 2 1 0 1 2 1
2 1 0 0 1 2 1 0 0 1 2
On fera deux versions du programme :
Une première version qui remplit un tableau à deux dimensions puis l'affiche
(en utilisant une procédure).
Une deuxième qui n'utilisera aucun tableau.
fichiers
Ecrire un programme qui copie un fichier de texte dans un autre en renversant
l'ordre des lettres dans chaque mot.
Par exemple, si le fichier marquise.txt contient
Marquise, vos beaux yeux me font mourir d'amour.
Lors de l'exécution du programme on verra :
Quel fichier voulez-vous renverser ? marquise.txt
Comment voulez-vous appeler la copie renversée ? esiuqram.txt
Le fichier esiuqram.txt sera créé et contiendra :
esiuqraM, sov xuaeb xuey em tnof riruom d'ruoma.