Mercredi 11 février 2004 : record
Mercredi 18 février 2004 : record suite
Mercredi 3 mars 2004 : fichiers text
Mercredi 10 mars 2004 : écriture et lecture de tableaux de record dans un fichier text
Mercredi 17 mars 2004 : lecture, écriture et produits de vecteurs et matrices
Mercredi 24 mars 2004 : système d'équations linéaires
Mercredi 31 mars 2004 : polynômes : addition, multiplication, degré
Mercredi 7 avril 2004 : polynômes : division, dérivée, méthode de Horner
Mercredi 28 avril 2004 : méthode de Newton et décomposition LU
Mercredi 5 mai 2004 : readkey
Mercredi 12 mai 2004 : fichiers binaires d'entiers
Mercredi 19 mai 2004 : fichier binaire de records, carnet d'adresses
Mercredi 26 mai 2004 : reorésentation des entiers et variantes de case
suivant sommaire
Mercredi 11 février 2004 : records
I nombres complexes :
Version 1 : tableau de deux nombres réels
type complexe=array[1..2] of real;
var a,b,c:complexe;
begin
a[1]:=4; a[2]:=1;
b[1]:=5; b[2]:=-1;
c[1]:=a[1]+b[1];
c[2]:=a[2]+b[2];
...
Version 2 : record, sans procédure
type complexe=record re,im:real end;
var a,b,c:complexe;
begin
a.re:=4; a.im:=1;
b.re:=5; b.im:=-1;
c.re:=a.re+b.re;
c.im:=a.im+b.im;
...
Version 3 : procédure d'addition (pascal standard)
type complexe=record re,im:real end;
procedure addc(x,y:complexe;var z:complexe);
begin
z.re:=x.re+y.re;
z.im:=x.im+y.im
end;
var a,b,c:complexe;
begin
a.re:=4; a.im:=1;
b.re:=5; b.im:=-1;
addc(a,b,c);
...
Version 4 : fonction d'addition (extension de free pascal)
type complexe=record re,im:real end;
function addc(x,y:complexe):complexe;
begin
addc.re:=x.re+y.re;
addc.im:=x.im+y.im
end;
var a,b,c:complexe;
begin
a.re:=4; a.im:=1;
b.re:=5; b.im:=-1;
c:=addc(a,b);
...
Version 5 : opérateur d'addition
type complexe=record re,im:real end;
operator + (x,y:complexe)z:complexe;
begin
z.re:=x.re+y.re;
z.im:=x.im+y.im
end;
var a,b,c:complexe;
begin
a.re:=4; a.im:=1;
b.re:=5; b.im:=-1;
c:=a+b;
...
Version 5 complétée : soustraction, multiplication, lecture et écriture
type complexe=record re,im:real end;
operator + (x,y:complexe)z:complexe;
begin
z.re:=x.re+y.re;
z.im:=x.im+y.im
end;
operator - (x,y:complexe)z:complexe;
begin
z.re:=x.re-y.re;
z.im:=x.im-y.im
end;
operator * (x,y:complexe)z:complexe;
begin
z.re:=x.re*y.re-x.im*y.im;
z.im:=x.im+y.re+x.re*y.im
end;
procedure writec(a:complexe);
begin
write('(');
write(a.re:0:5);
if a.im>0 then write('+');
if a.im<>0 then write(a.im:0:5,'i');
write(')')
end;
function readc:complexe;
begin
read(readc.re,readc.im)
end;
var a,b,c:complexe;
begin
a.re:=4; a.im:=1;
b.re:=5; b.im:=-1;
c:=a+b;
writec(a);write('+');writec(b);write('=');writec(c);writeln;
writeln('Tapez 2 nombres complexes et vous verrez leur somme.');
writec(readc+readc);
readln;
readln
end.
II record comtenant des champs de différents types.
type personne=record
nom,prenom:string[30];
age:integer;
sexe:(masculin,feminin)
end;
procedure writepersonne(a:personne);
begin
writeln(a.prenom,' ',a.nom,' ',a.age,' ');
case a.sexe of
masculin:write('M');
feminin :write('F')
end;
writeln
end;
procedure readpersonne(var a:personne);
var c:char;
begin
write('Nom ? ');readln(a.nom);
write('Prénom ? ');readln(a.prenom);
write('Age ? ');readln(a.age);
repeat
write('sexe ? '); readln(c); c:=upcase(c)
until (c='M') or (c='F') or (c='H');
if c='F' then a.sexe:=feminin
else a.sexe:=masculin
end;
function nomlong(a:personne):boolean;
begin nomlong:=length(a.nom)>length(a.prenom) end;
pour le TD prendre les trois dernières pages des
énoncés de TD du premier semestre.
suivant précédent sommaire
Mercredi 18 février 2004 : type énuméré et records(suite) : with, case, records imbriqués
type énuméré :
Un type énuméré se déclare comme une suite entre parenthèses de noms séparés par des virgules.
Cela définit ces noms comme des constantes de ce nouveau type.
Dans l'exemple suivant la variable f de type figure, peut prendre les
trois valeurs carre, cercle et triangle, qui sont en fait représentées dans l'ordinateur
comme les nombres entiers 0, 1 et 2.
La fonction ord transforme une figure en un entier.
La fonction réciproque figure transforme un entier en une figure.
Les types énumérés peuvent être utilisés comme les caractères, les booléens et les entiers
pour les variables de contrôle des boucles for, les cases et les indices de tableau.
En fait les booléens et les caractères se comportent un peu comme des types énumérès déclarés par
type boolean=(false,true);
char=(#0,#1,#2, .... ,'*', '+', ',', '-', '.', '/', '0', '1', ... #255);
Les fonctions succ, pred et ord s'appliquent à tous ces types. Par exemple
succ(3)=4, succ('A')='B', succ(false)=true, succ(cercle)=triangle,
pred(3)=2, pred('d')='c', pred(true)=false, pred(cercle)=carre,
ord(3)=3, ord('d')=100, ord(true)=1, ord(cercle)=1.
type figure=(carre,cercle,triangle);
var f:figure;
begin
f:=carre;
write(ord(f)); // ord(carre)=0
f:=succ(f); // succ(carre)=cercle
f:=succ(f); // succ(cercle)=triangle
f:=pred(f); // pred(triangle)=cercle
f:=pred(f); // pred(cercle)=carre
f:=figure(1); // figure(1)=cercle
for f:=carre to triangle do
begin
case f of
carre:write('carré');
cercle:write('cercle');
triangle:write('triangle');
end;
writeln(ord(f):2)
end;
readln
end.
Le programme précédent écrit
0carré 0
cercle 1
triangle 2
Le 0 devant carré provient du write(ord(f)).
Il aurait évidemment fallu écrire writeln(ord(f)) pour que le 0 soit
tout seul sur sa ligne.
points et figures :
type real=extended;
figure=(carre,cercle,triangle);
point=record x,y:real end;
fig=record
surface,perimetre:real;
case typfig:figure of
carre :(centre:point;
cote:real);
cercle :(centrec:point;
rayon:real);
triangle:(s:array[1..3] of point)
end;
const nomfig:array[figure] of string[8]=('carré','cercle','triangle');
procedure affpoint(a:point);
begin
with a do write('(', x:0:5, ',', y:0:5, ')')
end;
function dist(a,b:point):real;
begin
dist:=sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))
end;
procedure calculsurfaceperimetre(var f:fig);
begin
with f do
case typfig of
carre:
begin
surface:=sqr(cote);
perimetre:=4*cote
end;
cercle:
begin
surface:=sqr(rayon)*pi;
perimetre:=2*pi*rayon
end;
triangle:
begin
surface:=abs((s[1].x-s[2].x)*(s[1].y-s[3].y)
-(s[1].y-s[2].y)*(s[1].x-s[3].x))/2;
perimetre:=dist(s[1],s[2])+dist(s[2],s[3])+dist(s[3],s[1])
end
end
end;
procedure afffig(f:fig);
var i:integer;
begin
with f do
begin
writeln(nomfig[typfig]);
case typfig of
carre:
begin
write('centre : '); affpoint(centre); writeln;
writeln('longueur des cotés : ',cote:0:5)
end;
cercle:
begin
write('centre : '); affpoint(centre); writeln;
writeln('rayon : ',cote:0:5)
end;
triangle:
begin
write('sommets : ');
for i:=1 to 3 do affpoint(s[i]);
writeln
end
end;
writeln('surface ' ,surface :0:5);
writeln('perimètre ',perimetre:0:5)
end
end;
var ca,ce,tr:fig;
begin
ca.typfig:=carre;
ca.centre.x:=1;
ca.centre.y:=2;
ca.cote:=5;
ce.typfig:=cercle;
ce.centrec.x:=-1;
ce.centrec.y:=2.4;
ce.rayon:=5;
tr.typfig:=triangle;
tr.s[1].x:=0;
tr.s[1].y:=4;
tr.s[2].x:=3;
tr.s[2].y:=0;
tr.s[3].x:=-3;
tr.s[3].y:=0;
calculsurfaceperimetre(ca);
calculsurfaceperimetre(ce);
calculsurfaceperimetre(tr);
afffig(ca); writeln;
afffig(ce); writeln;
afffig(tr);
readln
end.
Le programme précédent écrit
carré
centre : (1.00000,2.00000)
longueur des cotés : 5.00000
surface 25.00000
perimètre 20.00000
cercle
centre : (-1.00000,2.40000)
rayon : 5.00000
surface 78.53982
perimètre 31.41593
triangle
sommets : (0.00000,4.00000)(3.00000,0.00000)(-3.00000,0.00000)
surface 12.00000
perimètre 16.00000
suivant précédent sommaire
Mercredi 3 mars 2004 : fichiers text
écriture sur l'écran
On peut écrire sur l'écran des nombres (entiers ou réels),
des caractères, des chaînes de caractères, des booleéns ou
des passages à la ligne : par exemple
write(3+4);
write('bonjour');
write(3.0);
write('x');
write(4<5);
write(succ('A'));
write(11+23:4);
write('bonjour':10);
write('bonjour':4);
write(3.0:7);
write(3.0:7:2);
write(7/3:0:4);
writeln
écrit sur l'écran une ligne :
7bonjour 3.0000000000000000E+0000xTRUEB 34 bonjourbonjour 3.0E+0000 3.002.3333
On aurait pu remplacer ces douze write et ce writeln par une seule instruction :
writeln(3+4,'bonjour',3.0,'x',4<5,succ('A'),11+23:4,
'bonjour':10,'bonjour':4,3.0:7,3.0:7:2,7/3:0:4)
écriture dans un fichier
Si on veut écrire une procédure qui affiche un vecteur de 7 entiers
sur l'écran on peut écrire :
const n=7;
type vec=array[1..n] of integer;
procedure affvec(a:vec);
var i:integer;
begin
for i:=1 to n do write(a[i]:10);
writeln
end;
Si, on veut que la procédure affvec puisse écrire un vecteur non seulement sur l'écran,
mais aussi dans un fichier, on peut faire :
const n=7;
type vec=array[1..n] of integer;
procedure affvec(var f:text;a:vec);
var i:integer;
begin
for i:=1 to n do write(f,a[i]:10);
writeln(f)
end;
var f:text;
a:vec;
i:integer;
begin
for i:=1 to n do a[i]:=23 mod i;
assign(f,'a:\truc.txt');
rewrite(f);
affvec(f,a); // écrit a dans le fichier
affvec(f,a); // écrit a une deuxième fois dans le fichier
affvec(output,a); // écrit a sur l'écran
for i:=2 to n do a[i]:=a[i]+a[a[i]];
affvec(f,a);
affvec(output,a);
close(f)
end.
Le programme précédent affiche sur l'écran
0 1 2 3 3 5 2
0 1 3 6 6 11 3
et crée le fichier a:\truc.txt qui contient
0 1 2 3 3 5 2
0 1 2 3 3 5 2
0 1 3 6 6 11 3
En fait output est un fichier prédéfini ouvert en sortie sur l'écran,
que l'on utilise souvent implicitement, puisque, par exemple
writeln(5,7) est équivalent à writeln(output,5,7) ou encore à
begin write(output,5); write(output,7); writeln(output) end
lecture de fichier text
Dans un fichier text on peut lire :
-un caractère (On ne doit pas être en fin de ligne)
-une chaîne de caractères : On lit des caractères jusqu'à ce que
la chaîne lue soit pleine ou qu'on atteigne la fin de la ligne.
On ne lit jamais de passage à la ligne. Si on était déjà en fin de
ligne avant la lecture, on y reste et la chaîne lue est vide.
-un nombre (entier ou réel): Tous les blancs et les passages à la ligne
précédant le nombre sont lus et ignorés, après le nombre il doit y avoir
un blanc (qui est lu) ou un passage à la ligne (qui n'est pas lu).
Si pendant la lecture on rencontre un caractère illégal (comme une
lettre dans un entier) alors il y a une erreur d'exécution qui arrête
le programme.
-un booleén
-un passage à la ligne : dans ce cas, tous les caractères rencontrés
jusqu'au prochain passage à la ligne sont lus et ignorés.
On peut utiliser les fonctions eoln (end of line) et eof (end of file)
qui permettent de savoir si on est en fin de ligne ou en fin de fichier.
exemple 1
Le programme suivant lit le fichier a:\2n.txt contenant
2 3
5 6
1 7
34 12
et affiche sur l'écran
2+3=5
5+6=11
1+7=8
34+12=46
var f:text;
x,y:integer;
begin
assign(f,'a:\2n.txt');
reset(f);
while not eof(f) do
begin
readln(f,x,y);
writeln(x,'+',y,'=',x+y)
end;
close(f)
end.
exemple 2
Le programme suivant lit un texte et le réécrit en remplaçant les minuscules
par des majuscules et réciproquement :
var f,g:text;
c:char;
begin
assign(f,'truc.txt');
reset(f);
assign(g,'troc.txt');
rewrite(g);
while not eof(f) do
if eoln(f) then
begin
readln(f);
writeln(g)
end else
begin
read(f,c);
if (c>='A') and (c<='Z') then c:=chr(ord(c)-ord('A')+ord('a')) else
if (c>='a') and (c<='z') then c:=chr(ord(c)-ord('a')+ord('A'));
write(g,c)
end;
close(f);
close(g)
end.
exemple 3
Le programme suivant compte les blancs dans un fichier :
var f:text;
c:char;
n:integer;
begin
n:=0;
assign(f,'truc.txt');
reset(f);
while not eof(f) do
if eoln(f) then readln(f) else
begin
read(f,c);
if c=' ' then n:=n+1
end;
close(f);
write('Il y a ',n,' blancs dans le fichier.');
readln
end.
exemple 4
Le programme suivant copie un fichier en éliminant
les blancs qui suivent un autre blanc :
var f,g:text;
c,d:char;
begin
assign(f,'truc.txt');
reset(f);
assign(g,'trac.txt');
rewrite(g);
d:='a';
while not eof(f) do
if eoln(f) then
begin
readln(f);
writeln(g);
d:='a'
end else
begin
read(f,c);
if(c<>' ') or (d<>' ') then write(g,c);
d:=c
end;
close(f);
close(g)
end.
suivant précédent sommaire
Mercredi 10 mars 2004 : écriture et lecture de tableaux de record dans un fichier text
résultat d'une journée de championnat
type resultat=(gagne,nul,perdu);
match=record equipe1,equipe2:string[20];
res:resultat
end;
journee=array[1..10] of match;
function opp(r:resultat):resultat;
begin
opp:=resultat(2-ord(r))
end;
procedure litjournee(var f:text;var jour:journee);
var i:integer;
c,d:char;
begin
for i:=1 to 10 do
with jour[i] do
begin
readln(f,c,equipe1);
readln(f,d,equipe2);
if (c='+') and (d='-') then res:=gagne else
if (c='=') and (d='=') then res:=nul else
if (c='-') and (d='+') then res:=perdu else
begin
writeln('Données incorrectes :');
writeln('i=',i);
writeln(c,equipe1);
writeln(d,equipe2);
halt
end;
readln(f)
end
end;
procedure ecritjournee(var f:text;jour:journee);
var i:integer;
const t:array[resultat] of char=('+','=','-');
begin
for i:=1 to 10 do
with jour[i] do
begin
writeln(f,t[ res ],equipe1);
writeln(f,t[opp(res)],equipe2);
writeln(f)
end
end;
var f:text;
nom:string[80];
j:journee;
begin
write('Quel fichier voulez-vous lire ? ');
readln(nom);
assign(f,nom);
reset(f);
litjournee(f,j);
ecritjournee(output,j);
close(f);
write('Dans quel fichier voulez-vous écrire ? ');
readln(nom);
assign(f,nom);
(*$i-*)
append(f);
(*$i+*)
if ioresult<>0 then rewrite(f);
ecritjournee(f,j);
close(f)
end.
Le programme précédent lit les trente lignes suivantes dans un fichier,
puis les écrit sur l'écran et les rajoute à la fin d'un autre fichier.
+Guingamp
-Lens
=Bastia
=Lyon
+Ajaccio
-Marseille
-Toulouse
+Metz
=Sochaux
=Lille
+Monaco
-Montpellier
+Bordeaux
-Nantes
+Auxerre
-Nice
=PSG
=Rennes
-Le Mans
+Strasbourg
suivant précédent sommaire
Mercredi 17 mars 2004 : lecture, écriture et produits de vecteurs et matrices
type real=extended;
const n=3;
type vec=array[1..n] of real;
mat=array[1..n] of vec;
procedure ecrvec(var f:text;a:vec);
var i:integer;
begin
for i:=1 to n do write(f,a[i]:30);
writeln(f)
end;
procedure ecrmat(var f:text;a:mat);
var i:integer;
begin
writeln(f);
for i:=1 to n do ecrvec(f,a[i])
end;
procedure lirvec(var f:text;var a:vec);
var i:integer;
begin
for i:=1 to n do read(f,a[i]);
readln(f)
end;
procedure lirmat(var f:text;var a:mat);
var i:integer;
begin
for i:=1 to n do lirvec(f,a[i])
end;
operator +(a,b:vec)c:vec;
var i:integer;
begin
for i:=1 to n do c[i]:=a[i]+b[i]
end;
operator +(a,b:mat)c:mat;
var i:integer;
begin
for i:=1 to n do c[i]:=a[i]+b[i]
end;
operator -(a,b:vec)c:vec;
var i:integer;
begin
for i:=1 to n do c[i]:=a[i]-b[i]
end;
operator -(a,b:mat)c:mat;
var i:integer;
begin
for i:=1 to n do c[i]:=a[i]-b[i]
end;
operator *(a:mat;b:vec)c:vec;
var i,j:integer;
s:real;
begin
for i:=1 to n do
begin
s:=0;
for j:=1 to n do s:=s+a[i,j]*b[j];
c[i]:=s
end
end;
operator *(a,b:mat)c:mat;
var i,j,k:integer;
s:real;
begin
for i:=1 to n do
for k:=1 to n do
begin
s:=0;
for j:=1 to n do s:=s+a[i,j]*b[j,k];
c[i,k]:=s
end
end;
function trace(a:mat):real;
var i:integer;
s:real;
begin
s:=0;
for i:=1 to n do s:=s+a[i,i];
trace:=s
end;
function norme1(a:vec):real;
var i:integer;
s:real;
begin
s:=0;
for i:=1 to n do s:=s+abs(a[i]);
norme1:=s
end;
function normem1(a:mat):real;
var i:integer;
s:real;
begin
s:=0;
for i:=1 to n do s:=s+norme1(a[i]);
normem1:=s
end;
var a,b,c,ab,bc,ca:mat;
v:vec;
i,j:integer;
f:text;
begin
for i:=1 to n do
for j:=1 to n do
begin
a[i,j]:=i*i+j+i xor j;
b[i,j]:=i*i-j-i and j;
c[i,j]:=i div j-j mod i
end;
write('a:');ecrmat(output,a);
write('b:');ecrmat(output,b);
write('c:');ecrmat(output,c);
ab:=a*b;
bc:=b*c;
ca:=c*a;
write('ab:');ecrmat(output,ab);
write('bc:');ecrmat(output,bc);
write('ca:');ecrmat(output,ca);
writeln('|a*bc-ab*c|=',normem1(a*bc-ab*c));
writeln('Tr(abc)=',trace(ab*c));
writeln('Tr(bca)=',trace(bc*a));
writeln('Tr(cab)=',trace(ca*b));
for i:=1 to n do v[i]:=i*7 div 4;
writeln('|a*(b*v)-ab*v|=',norme1(a*(b*v)-ab*v));
writeln('|b*(c*v)-bc*v|=',norme1(b*(c*v)-bc*v));
assign(f,'truc');
rewrite(f);
ecrmat(f,a);
ecrmat(f,b);
close(f);
reset(f);
lirmat(f,ab);
lirmat(f,bc);
close(f);
write('|ab-a|=',normem1(ab-a),' ab=');ecrmat(output,ab);
write('|bc-b|=',normem1(bc-b),' bc=');ecrmat(output,bc);
readln
end.
suivant précédent sommaire
Mercredi 24 mars 2004 : système d'équations linéaires
type real=extended;
const n=3;
type vec=array[1..n] of real;
mat=array[1..n] of vec;
veci=array[1..n] of integer;
procedure ecrvec(var f:text;a:vec);
var i:integer;
begin
for i:=1 to n do write(f,a[i]:12:6);
writeln(f)
end;
procedure ecrmat(var f:text;a:mat);
var i:integer;
begin
writeln(f);
for i:=1 to n do ecrvec(f,a[i])
end;
procedure lirvec(var f:text;var a:vec);
var i:integer;
begin
for i:=1 to n do read(f,a[i]);
readln(f)
end;
procedure lirmat(var f:text;var a:mat);
var i:integer;
begin
for i:=1 to n do lirvec(f,a[i])
end;
operator +(a,b:vec)c:vec;
var i:integer;
begin
for i:=1 to n do c[i]:=a[i]+b[i]
end;
operator +(a,b:mat)c:mat;
var i:integer;
begin
for i:=1 to n do c[i]:=a[i]+b[i]
end;
operator -(a,b:vec)c:vec;
var i:integer;
begin
for i:=1 to n do c[i]:=a[i]-b[i]
end;
operator -(a,b:mat)c:mat;
var i:integer;
begin
for i:=1 to n do c[i]:=a[i]-b[i]
end;
operator *(a:mat;b:vec)c:vec;
var i,j:integer;
s:real;
begin
for i:=1 to n do
begin
s:=0;
for j:=1 to n do s:=s+a[i,j]*b[j];
c[i]:=s
end
end;
operator *(a,b:mat)c:mat;
var i,j,k:integer;
s:real;
begin
for i:=1 to n do
for k:=1 to n do
begin
s:=0;
for j:=1 to n do s:=s+a[i,j]*b[j,k];
c[i,k]:=s
end
end;
function trace(a:mat):real;
var i:integer;
s:real;
begin
s:=0;
for i:=1 to n do s:=s+a[i,i];
trace:=s
end;
function norme1(a:vec):real;
var i:integer;
s:real;
begin
s:=0;
for i:=1 to n do s:=s+abs(a[i]);
norme1:=s
end;
function normem1(a:mat):real;
var i:integer;
s:real;
begin
s:=0;
for i:=1 to n do s:=s+norme1(a[i]);
normem1:=s
end;
function resoutgauss(a:mat;b:vec):vec;
var c:vec;
i,j,m:integer;
p:real;
begin
for m:=1 to n do
begin
(* recherche du plus gros coefficient de la colonne m sur
la diagonale et en dessous i.e. dans a[m..n,m] *)
i:=m;
for j:=m to n do if abs(a[j,m])>abs(a[i,m]) then i:=j;
(* échange des équations m et i *)
c:=a[i]; a[i]:=a[m]; a[m]:=c;
p:=b[i]; b[i]:=b[m]; b[m]:=p;
(* division de l'équation m par a[m,m] pour faire apparaître
un 1 sur la diagonale *)
p:=a[m,m];
if p=0 then begin writeln('matrice non inversible');halt end;
for j:=m to n do a[m,j]:=a[m,j]/p;
b[m]:=b[m]/p;
(* A chacune des lignes en dessous du pivot, on soustrait un multiple
de la ligne du pivot pour faire apparaître un 0 sous le pivot *)
for i:=m+1 to n do
begin
p:=a[i,m];
for j:=m to n do a[i,j]:=a[i,j]-p*a[m,j];
b[i]:=b[i]-p*b[m]
end
end;
(* La matrice a est triangulaire supérieure *)
(* Résolution de ce sytème triangulaire *)
for i:=n downto 1 do
begin
p:=b[i];
for j:=i+1 to n do p:=p-a[i,j]*c[j];
c[i]:=p
end;
resoutgauss:=c
end;
(* On peut diviser la procédure précédente en deux :
Dans la première on mettra tous les calculs qui ne dépendent que de
la matrice A. Le temps de ces calculs est en O(n³).
Dans la deuxième on mettra tous les calculs qui dépendent aussi du vecteur
B. Le temps de ces calculs est en O(n²).
De cette façon si on veut résoudre plusieurs systèmes d'équations linéaires
ayant la même matrice mais des membres droits différents, on ne fera qu'une
fois le calcul en O(n³) qui dépend de la matrice, et on ne répètera que le
calcul en O(n²). Cela permet en particulier de calculer l'inverse d'une
matrice avec O(n³) opérations élémentaires (comme pour le produit de deux
matrices). *)
procedure decomplu(var a:mat;var b:veci);
var i,j,m:integer;
c:vec;
p:real;
begin
for i:=1 to n do b[i]:=i; (* numérotation initiale des lignes *)
for m:=1 to n do
begin
(* recherche du plus gros coefficient de la colonne m sur
la diagonale et en dessous i.e. dans a[m..n,m] *)
i:=m;
for j:=m to n do if abs(a[j,m])>abs(a[i,m]) then i:=j;
(* échange des équations m et i *)
c:=a[i]; a[i]:=a[m]; a[m]:=c;
j:=b[i]; b[i]:=b[m]; b[m]:=j;
(* division de l'équation m par a[m,m] pour faire apparaître
un 1 sur la diagonale *)
p:=a[m,m];
if p=0 then begin writeln('matrice non inversible');halt end;
for j:=m+1 to n do a[m,j]:=a[m,j]/p;
(* A chacune des lignes en dessous du pivot, on soustrait un multiple
de la ligne du pivot pour faire apparaître un 0 sous le pivot *)
for i:=m+1 to n do
begin
p:=a[i,m];
for j:=m+1 to n do a[i,j]:=a[i,j]-p*a[m,j];
end
end
end;
function resoutlu(a:mat;bb:veci;b:vec):vec;
var i,j:integer;
p:real;
c:vec;
begin
c:=c;
for i:=1 to n do
begin
p:=b[bb[i]];
for j:=1 to i-1 do p:=p-a[i,j]*c[j];
c[i]:=p/a[i,i]
end;
for i:=n downto 1 do
begin
p:=c[i];
for j:=i+1 to n do p:=p-a[i,j]*c[j];
c[i]:=p
end;
resoutlu:=c
end;
function transpose(a:mat):mat;
var i,j:integer;
begin
for i:=1 to n do
for j:=1 to n do transpose[i,j]:=a[j,i]
end;
function invmat(a:mat):mat;
var i:integer;
bb:veci;
b:vec;
begin
a:=transpose(a);
decomplu(a,bb);
for i:=1 to n do b[i]:=0;
for i:=1 to n do
begin
b[i]:=1;
invmat[i]:=resoutlu(a,bb,b);
b[i]:=0
end
end;
var a,b,c,ab,bc,ca:mat;
v:vec;
bb:veci;
i,j:integer;
f:text;
begin
for i:=1 to n do
for j:=1 to n do
begin
a[i,j]:=i*i-j*j+i xor j;
b[i,j]:=i*i-j-i and j;
c[i,j]:=i div j-j mod i
end;
write('a:');ecrmat(output,a);
write('b:');ecrmat(output,b);
write('c:');ecrmat(output,c);
ab:=a*b;
bc:=b*c;
ca:=c*a;
write('ab:');ecrmat(output,ab);
write('bc:');ecrmat(output,bc);
write('ca:');ecrmat(output,ca);
writeln('|a*bc-ab*c|=',normem1(a*bc-ab*c));
writeln('Tr(abc)=',trace(ab*c));
writeln('Tr(bca)=',trace(bc*a));
writeln('Tr(cab)=',trace(ca*b));
for i:=1 to n do v[i]:=i*7 div 4;
writeln('|a*(b*v)-ab*v|=',norme1(a*(b*v)-ab*v));
writeln('|b*(c*v)-bc*v|=',norme1(b*(c*v)-bc*v));
assign(f,'truc');
rewrite(f);
ecrmat(f,a);
ecrmat(f,b);
close(f);
reset(f);
lirmat(f,ab);
lirmat(f,bc);
close(f);
write('|ab-a|=',normem1(ab-a),' ab=');ecrmat(output,ab);
write('|bc-b|=',normem1(bc-b),' bc=');ecrmat(output,bc);
write(' v= ');ecrvec(output,v);
write('a*v= ');ecrvec(output,a*v);
write('(1/a)*a*v= ');ecrvec(output,resoutgauss(a,a*v));
ab:=a;
decomplu(ab,bb);
write('(1/a)*a*v= ');ecrvec(output,resoutlu(ab,bb,a*v));
write('a*(1/a)='); ecrmat(output,a*invmat(a));
readln
end.
interprétation matricielle de la méthode de Gauss
suivant précédent sommaire
Mercredi 31 mars 2004 : polynômes : addition, multiplication, degré
suivant précédent sommaire
Mercredi 7 avril 2004 : polynômes : division, dérivée, méthode de Horner
const dmax=30;
type real=extended;
poly=array[0..dmax] of real;
poly2=record degre:integer;coeff:poly end;
procedure affpoly(a:poly);
var i:integer;
x:real;
nul:boolean;
begin
nul:=true;
for i:=dmax downto 0 do if a[i]<>0 then
begin
x:=a[i];
if x<0 then write('-') else
if not nul then write('+');
x:=abs(x);
if int(x)=x then if (x=1) and (i>0) then
else write(x:0:0)
else if x<1 then write(x:10)
else write(x:0:6);
case i of
0:;
1:write('X');
2:write('X²');
else write('X^',i)
end;
nul:=false
end;
if nul then write(0)
end;
function degre(a:poly):integer;
begin
degre:=dmax;
while (degre>=0) and (a[degre]=0) do degre:=degre-1
end;
procedure caldeg(var a:poly2);
begin
with a do while (degre>=0) and (coeff[degre]=0) do degre:=degre-1
end;
operator+(a,b:poly)c:poly;
var i:integer;
begin
for i:=0 to dmax do c[i]:=a[i]+b[i]
end;
operator+(a,b:poly2)c:poly2;
var i:integer;
begin
if a.degredmax then
begin
writeln('produit de degré trop élevé ',da,' + ',db);
halt
end;
for i:=0 to dmax do c[i]:=0;
for i:=0 to da do if a[i]<>0 then
for j:=0 to db do c[i+j]:=c[i+j]+a[i]*b[j]
end;
operator*(a,b:poly2)c:poly2;
var i,j:integer;
begin
if (a.degre=-1) or (b.degre=-1) then c.degre:=-1
else c.degre:=a.degre+b.degre;
if c.degre>dmax then
begin
writeln('produit de degré trop élevé ',a.degre,' + ',b.degre);
halt
end;
for i:=0 to c.degre do c.coeff[i]:=0;
for i:=0 to a.degre do if a.coeff[i]<>0 then
for j:=0 to b.degre do
c.coeff[i+j]:=c.coeff[i+j]+a.coeff[i]*b.coeff[j]
end;
procedure divpoly(a,b:poly;var q,r:poly);
var da,db,i:integer;
p:real;
begin
db:=degre(b);
if db=-1 then
begin
writeln('division par 0');
halt
end;
for i:=0 to dmax do q[i]:=0;
for da:=degre(a) downto db do
begin
p:=a[da]/b[db];
q[da-db]:=p;
if p<>0 then
for i:=da-db to da-1 do a[i]:=a[i]-p*b[i-da+db];
a[da]:=0
end;
r:=a
end;
function pgcd(a,b:poly):poly;
var q,r:poly;
begin
while degre(b)>=0 do
begin
divpoly(a,b,q,r);
a:=b;
b:=r
end;
pgcd:=a
end;
function val(a:poly;x:real):real;
var i:integer;
begin
val:=0;
for i:=dmax downto 0 do val:=val*x+a[i]
end;
function derivee(a:poly):poly;
var i:integer;
begin
for i:=1 to dmax do derivee[i-1]:=i*a[i];
derivee[dmax]:=0
end;
suivant précédent sommaire
Mercredi 28 avril 2004 : méthode de Newton et décomposition LU
interprétation matricielle de la méthode de Gauss
type fonc=function(x:real):real;
function newton(f,df:fonc;x:real):real;
var y:real;
begin
repeat
y:=x;
x:=x-f(x)/df(x)
until x=y;
newton:=x
end;
function f1(x:real):real; begin f1:=sin(x)-0.7 end;
function df1(x:real):real; begin df1:=cos(x) end;
function newtonpoly(p:poly;x:real):real;
var y,px,dpx:real;
d,i:integer;
begin
d:=degre(p);
repeat
y:=x;
px:=0;
dpx:=0;
for i:=d downto 0 do
begin
dpx:=dpx*x+px;
px:= px*x+p[i]
end;
x:=x-px/dpx
until x=y;
newtonpoly:=x
end;
var a,b,c:poly;
i:integer;
x:real;
begin
for i:=0 to dmax do a[i]:=0;
b:=a;
c:=a;
a[0]:=1; a[10]:=1; a[20]:=1;
b[0]:=1; b[13]:=1; b[26]:=1;
c[0]:=1; c[ 1]:=1; c[11]:=1;
affpoly(pgcd(a,b)); writeln;
x:=newton(@f1,@df1,0); writeln('sin(',x:0:18,')=',sin( x):0:18);
x:=newtonpoly(c ,0); writeln('c (',x:0:18,')=',val(c,x):0:18);
readln
end.
suivant précédent sommaire
Mercredi 5 mai 2004 : readkey
Le programme suivant permet de voir le code de toute touche tapée au clavier.
uses crt;
var c:char;
begin
repeat
c:=readkey;
writeln(ord(c))
until (c='q') or (c='Q') or (c=#3)
end.
Le programme suivant affiche un message différent pour chacune des touches tapées au clavier
qu'il reconnaît.
uses crt;
begin
while true do
case upcase(readkey) of
'A':writeln('alpha');
'B':writeln('bravo');
'C':writeln('charly');
'D':writeln('delta');
'E':writeln('echo');
'F':writeln('fox-trot');
'G':writeln('golf');
'H':writeln('hotel');
'I':writeln('india');
'J':writeln('juliette');
'K':writeln('kilo');
'L':writeln('lima');
'M':writeln('mike');
'N':writeln('november');
'O':writeln('oscar');
'P':writeln('papa');
'Q':begin writeln('quebec');halt end;
'R':writeln('romeo');
'S':writeln('sierra');
'T':writeln('tango');
'U':writeln('uniforme');
'V':writeln('victor');
'W':writeln('whisky');
'X':writeln('x-ray');
'Y':writeln('yankee');
'Z':writeln('zoulou');
'0':writeln('zero');
'1':writeln('un');
'2':writeln('deux');
'3':writeln('trois');
'4':writeln('quatre');
'5':writeln('cinq');
'6':writeln('six');
'7':writeln('sept');
'8':writeln('huit');
'9':writeln('neuf');
'+':writeln('plus');
'-':writeln('moins');
',':writeln('virgule');
':':writeln('deux points');
'''':writeln('apostrophe');
'"':writeln('guillemet');
'&':writeln('et commercial');
#0:case readkey of
#75:writeln('vers la gauche');
#77:writeln('vers la droite');
#72:writeln('vers le haut');
#80:writeln('vers le bas');
end;
#3:begin writeln('ctrl C');halt end;
#8:writeln('ctrl H ou backspace');
#10:writeln('ctrl J ou (line feed)');
#13:writeln('ctrl M ou (carriage return) ou entrée');
#26:writeln('ctrl Z');
#27:writeln('échappement');
' ':writeln('blanc');
'=':writeln('égale');
end
end.
suivant précédent sommaire
Mercredi 12 mai 2004 : fichiers binaires d'entiers
création d'un fichier
program creef1;
type fic=file of integer;
var f:fic;
i,j:integer;
begin
assign(f,'f1.int');
rewrite(f);
for i:=1 to 10 do
begin
j:=i*i+1;
write(f,j)
end;
close(f)
end.
affichage sur l'écran d'un fichier existant
program afff1;
var f:file of integer;
nom:string;
j:integer;
begin
write('Nom du fichier binaire d''entiers à afficher : ');
readln(nom);
assign(f,nom);
reset(f);
while not eof(f) do
begin
read(f,j);
write(j,' ')
end;
close(f);
readln
end.
modification de F1: mélange de read et write
program f1sur2;
var f:file of integer;
j:integer;
begin
assign(f,'f1.int');
reset(f);
while not eof(f) do
begin
read(f,j);
j:=j+2;
write(f,j)
end;
close(f);
readln
end.
affichage à l'envers sur l'écran d'un fichier existant
program aff1f;
var f:file of integer;
i,j:integer;
begin
assign(f,'f1.int');
reset(f);
for i:=filesize(f)-1 downto 0 do
begin
seek(f,i);
read(f,j);
write(j,' ')
end;
close(f);
readln
end.
concaténation de deux fichiers
Le programme suivant met f1 suivi de f2 dans f3.
program concat;
var f1,f2,f3:file of integer;
nom:string;
j:integer;
begin
repeat
write('Nom du premier fichier : ');
readln(nom);
assign(f1,nom);
(*$i-*)
reset(f1)
(*$i+*)
until ioresult=0;
repeat
write('Nom du deuxième fichier : ');
readln(nom);
assign(f2,nom);
(*$i-*)
reset(f2)
(*$i+*)
until ioresult=0;
repeat
write('Nom du fichier à créer : ');
readln(nom);
assign(f3,nom);
(*$i-*)
rewrite(f3)
(*$i+*)
until ioresult=0;
while not eof(f1) do
begin
read(f1,j);
write(f3,j)
end;
while not eof(f2) do
begin
read(f2,j);
write(f3,j)
end;
close(f1);
close(f2);
close(f3);
write('C''est fait.');
readln
end.
Si on compile tous ces programmes,
puis qu'on les exécute dans une fenêtre dos, on verra par exemple :
C:\users\lpierre\freepascal>creef1
C:\users\lpierre\freepascal>afff1
Nom du fichier binaire d'entiers à afficher : f1.int
2 5 10 17 26 37 50 65 82 101
C:\users\lpierre\freepascal>copy f1.int f2.int
1 fichier(s) copié(s).
C:\users\lpierre\freepascal>f1sur2
C:\users\lpierre\freepascal>afff1
Nom du fichier binaire d'entiers à afficher : f1.int
2 4 10 12 26 28 50 52 82 84
C:\users\lpierre\freepascal>aff1f
84 82 52 50 28 26 12 10 4 2
C:\users\lpierre\freepascal>concat
Nom du premier fichier : f1.int
Nom du deuxième fichier : f2.int
Nom du fichier à créer : f12.int
C'est fait.
C:\users\lpierre\freepascal>afff1
Nom du fichier binaire d'entiers à afficher : f12.int
2 4 10 12 26 28 50 52 82 84 2 5 10 17 26 37 50 65 82 101
suivant précédent sommaire
Mercredi 19 mai 2004 : fichier binaire de records, carnet d'adresses
Avant d'ouvrir un fichier il faut d'abord indiquer sur quel disque et dans quel répertoire
il se trouve et sous quel nom. On utilise
procedure assign(var f:file of ...;nom:string);
par exemple assign(f,'a:\animaux\chats.dat') indique que f sera un fichier appelé chats.dat
situé dans le répertoire animaux sur la disquette.
Il y a trois façons d'ouvrir un fichier :
procedure reset(var f:file of ...);
procedure rewrite(var f:file of ...);
procedure append(var f:file of ...);
reset et append supposent que le fichier existe déjà. Il est ouvert tel quel.
Reset met le pointeur d'enregistrement au début du fichier et permet donc
d'examiner le fichier à partir du début.
Append met le pointeur d'enregistrement à la fin du fichier et permet donc d'aggrandir le fichier
en le prolongeant par la fin.
Rewrite permet de créer un nouveau fichier vide, en effaçant éventuellement le contenu du fichier
s'il existait déjà.
Une fois qu'un fichier binaire est ouvert on peut lire et écrire dedans (on peut mélanger les
read et les write), contrairement aux fichiers text qui sont ouverts en lecture seule ou en écriture seule.
(Reset permet de lire un fichier text, alors que
rewrite et append permmettent d'écrire dedans.)
On peut utiliser read pour regarder le contenu d'un fichier et write pour le modifier.
procedure read(var f:file of element;var x:element);
procedure write(var f:file of element;var x:element);
read(f,x) copie un enregistrement du fichier dans la variable x.
write(f,x) copie la variable x dans un enregistrement du fichier.
Dans les deux cas le pointeur d'enregistrement du fichier avance d'un enregistrement.
Il était avant l'enregistrement lu ou écrit et il passe après cet enregistrement.
Si on est à la fin du fichier avant d'exécuter un read, il se produit une erreur
d'exécution.
Si on est à la fin du fichier avant d'exécuter un write, le fichier s'allonge avec un nouvel
enregistrement.
On peut contrôler la position du pointeur d'enregistrement en utilisant :
function eof(var f:file of ...):boolean;
function filepos(var f:file of ...):integer;
function filesize(var f:file of ...):integer;
procedure seek(var f:file of ...;p:integer);
eof(f) indique si le pointeur d'enregistrement est à la fin du fichier (End Of File).
filepos(f) indique combien d'enregistrements se trouvent avant le pointeur d'enregistrement.
Par exemple filepos(f) vaut 0 si le pointeur d'enregistrement est en début de fichier et
le nombre total d'enregistrement du fichier si le pointeur d'enregistrement est en fin de fichier.
filesize(f) est le nombre total de d'enregistrement du fichier.
Donc par exemple les deux expressions eof(f) et filepos(f)=filesize(f) sont
équivalentes.
seek(f,p) place le pointeur d'enregistrement après les p premiers.
Autrement dit seek(f,p) déplace le pointeur d'enregistrement de tel sorte que
filepos(f) vaille p.
Il y a deux façons de modifier la taille d'un fichier.
On peut l'augmenter en écrivant au delà de la fin du fichier.
On peut la diminuer en utilisant :
procedure truncate(var f:file of ...);
qui élimine du fichier tous les enregistrements au delà du pointeur d'enregistrement.
Par exemple, après seek(f,3);truncate(f) il n'y a plus que 3 enregistrements dans le fichier.
Quand on a fini d'utiliser un fichier il faut le fermer, pour être sûr que toutes ses modifications
sont bien effectuées sur le disque ou la disquette. On utilise :
procedure close(var f:file of ...);
Après l'avoir fermé on ne pourra lire ou écrire dedans, qu'après l'avoir réouvert.
Mais il n'est pas nécessaire de refaire l'appel à assign.
Si on veut seulement s'assurer que le fichier sur disque est à jour mais en continuant
de l'utiliser, au lieu de faire k:=filepos(f);close(f);reset(f);seek(f,k)
on peut faire plus simplement flush(f)
On ne peut pas passer des fichiers par valeur à une procédure (on est obligé de mettre var),
on ne peut pas non plus faire d'affectation de fichier.
Le programme suivant gère un carnet d'adresses dans un fichier.
uses crt;
type personne=record
nom,prenom:string[30];
age:integer;
portable,maison,boulot:string[10];
adresse:string[100];
codepostal:longint
end;
var f:file of personne;
procedure ouvrir;
var nom:string;
begin
repeat
write('nom du fichier : ');
readln(nom);
assign(f,nom);
(*$i+*)
reset(f);
if ioresult<>0 then rewrite(f)
(*$i-*)
until ioresult=0
end;
procedure precedent;
begin
if filepos(f)>0 then seek(f,filepos(f)-1)
end;
procedure suivant;
begin
if not eof(f) then seek(f,filepos(f)+1)
end;
procedure aff;
var p:personne;
begin
if eof(f) then exit;
read(f,p); precedent;
writeln('Nom : ',p.nom);
writeln('Prénom : ',p.prenom);
writeln('Age : ',p.age);
writeln('Numéro de téléphone portable : ',p.portable);
writeln('Numéro de téléphone à la maison : ',p.maison);
writeln('Numéro de téléphone au travail : ',p.boulot);
writeln('Adresse : ',p.adresse);
writeln('Code postal : ',p.codepostal)
end;
procedure creer;
var p:personne;
begin
write('Nom : ');readln(p.nom);
write('Prénom : ');readln(p.prenom);
repeat
(*$i+*)
write('Age : ');readln(p.age)
(*$i-*)
until ioresult=0;
write('Numéro de téléphone portable : ');readln(p.portable);
write('Numéro de téléphone à la maison : ');readln(p.maison);
write('Numéro de téléphone au travail : ');readln(p.boulot);
write('Adresse : ');readln(p.adresse);
repeat
(*$i+*)
write('Code postal : ');readln(p.codepostal)
(*$i-*)
until ioresult=0;
seek(f,filesize(f));
write(f,p);
precedent
end;
procedure supprimer;
var p:personne;
i:integer;
c:char;
begin
if eof(f) then exit;
aff;
write('Voulez vous le supprimer ?');
readln(c);
if upcase(c)<>'O' then exit;
i:=filepos(f);
seek(f,filesize(f)-1);
read(f,p);
seek(f,i);
write(f,p);
seek(f,filesize(f)-1);
truncate(f);
seek(f,i)
end;
procedure cherchenom;
var p:personne;
nom:string;
c:char;
begin
write('Quel nom cherche-t-on ? ');
readln(nom);
seek(f,0);
while not eof(f) do
begin
read(f,p);
if pos(nom,p.nom)<>0 then
begin
precedent; aff;
write('Est-ce la bonne personne ? ');
readln(c);
if upcase(c)='O' then exit;
suivant
end
end
end;
procedure modifier;
begin
(* à compléter *)
end;
begin
ouvrir;
while true do
case upcase(readkey) of
'P':precedent;
'S':suivant;
'A':aff;
'C':creer;
'E':supprimer;
'M':modifier;
'N':cherchenom;
'Q':begin close(f); exit end;
else writeln('Précédent Suivant Afficher Creer Effacer Modifier chercheNom Quitter')
end
end.
précédent sommaire
Mercredi 26 mai 2004 : reorésentation des entiers et variantes de case
Un ensemble de n bits peut prendre 2n valeurs, qui peuvent représenter les entiers
modulo 2n ou les entiers "non signés" de 0 à 2n-1 ou encore les entiers "signés"
de -2n-1 à 2n-1-1.
Ces trois représentations sont équivalentes tant qu'on ne fait que des additions, des soustractions
ou des multiplications. Elles ne diffèrent que quand on veut écrire un nombre en décimal,
diviser deux nombres ou comparer deux nombres.
Par exemple le nombre dont tous les bits valent 1 représente 2n-1 s'il est non signé ou
-1 s'il est signé mais dans les deux cas quand on lui ajoute 1, on obtient 0, et quand on prend son
opposé ou son carré on obtient 1.
En effet -1+1=0 et -(-1)=1 et (-1)2=1 tandis que
(2n-1)+1=2n sort de l'intervalle 0..2n-1, on l'y ramène en lui soustrayant
2n ce qui donne 0.
De même -(2n-1)=-2n+1 est trop petit, on lui ajoute 2n ce qui donne 1.
Enfin (2n-1)2=22n-2n+1+1 est beaucoup trop grand, on lui
enlève 22n-2n+1 qui est un multiple de 2n, ce qui donne 1.
Le nombre 345 a trois chiffres décimaux : un chiffre des unités 5 de poids 1,
un chiffre des dizaines 4 de poids 10 et un chiffre des centaines 3 de poids 102.
Autrement dit 345=3x102+4x10+5x1.
De même quand on écrit un nombre en binaire (c'est-à-dire en base 2) il est formé de plusieurs
chiffres binaires (en anglais BInary digITs ou bits) qui valent chacun 0 ou 1 et qui ont pour poids
1, 2, 4, 8, etc. à partir de la gauche.
Par exemple 1001101=1x26+0x25+0x24+1x23+1x22+0x2+1=64+8+4+1=77.
Quand un nombre est non signé, le poids de son bit le plus à gauche est 2n-1.
Quand un nombre est signé, le poids de son bit le plus à gauche est remplacé par -2n-1.
Le tableau suivant montre toutes les valeurs possibles d'un nombre de 4 bits.
| non signé | signé |
0000 | 0 | 0 |
0001 | 1 | 1 |
0010 | 2 | 2 |
0011 | 3=2+1 | 3=2+1 |
0100 | 4 | 4 |
0101 | 5=4+1 | 5=4+1 |
0110 | 6=4+2 | 6=4+2 |
0111 | 7=4+2+1 | 7=4+2+1 |
1000 | 8 | -8 |
1001 | 9=8+1 | -7=-8+1 |
1010 | 10=8+2 | -6=-8+2 |
1011 | 11=8+2+1 | -5=-8+2+1 |
1100 | 12=8+4 | -4=-8+4 |
1101 | 13=8+4+1 | -3=-8+4+1 |
1110 | 14=8+4+2 | -2=-8+4+2 |
1111 | 15=8+4+2+1 | -1=-8+4+2+1 |
Dans un PC les bits sont regroupés par 8 et forment des "octets".
En free pascal comme en turbo pascal il y a plusieurs type entiers prédéfinis dont certains sont signés
et d'autres non. Ils diffèrent aussi par leur taille.
BYTE et SHORTINT sont sur un octet, c'est-à-dire 8 bits.
INTEGER et WORD sont sur deux octets, c'est-à-dire 16 bits.
LONGINT est sur 4 octets, c'est-à-dire 32 bits.
BYTE et WORD ne sont pas signés. SHORTINT, INTEGER et LONGINT sont signés.
Tout se passe comme s'ils avaient été déclarés par
type byte=0..255;
shortint=-128..127;
word=0..65535;
integer=-32768..32767;
longint=-2147483648..2147483647;
Mais ces types son prédéfinis, il n'est donc pas nécessaire de les redéclarer.
Dans une variante d'un record, entre ( et ) on peut mettre une liste de champs comme entre record et end.
Cette liste peut donc contenir des variantes qui peuvent elles même contenir des variantes, etc..
var a:packed record
case integer of
0:(l:longint);
1:(w0:word; w1:integer);
2:(b0,b1,b2:byte;
case boolean of
false:(b3:byte);
true :(s3:shortint)
);
3:(c0,c1,c2,c3:char)
end;
begin
a.l:=-1;
writeln(a.l);
writeln(a.w0:10,a.w1:10);
writeln(a.b0:5,a.b1:5,a.b2:5,a.b3:5,'/',a.s3);
a.l:=530;
writeln(a.l);
writeln(a.w0:10,a.w1:10);
writeln(a.b0:5,a.b1:5,a.b2:5,a.b3:5,'/',a.s3);
a.c0:='A';
writeln(a.l);
writeln(a.w0:10,a.w1:10);
writeln(a.b0:5,a.b1:5,a.b2:5,a.b3:5,'/',a.s3);
a.w1:=1000;
writeln(a.l);
writeln(a.w0:10,a.w1:10);
writeln(a.b0:5,a.b1:5,a.b2:5,a.b3:5,'/',a.s3);
readln
end.
w0 est la moitié basse de l, w1 est la moitié haute de l.
b0 et c0 occupent la même place mémoire qui est la moitié basse de w0 et le quart bas de l.
b1 et c1 occupent la même place mémoire qui est la moitié haute de w0 et un quart de l.
b2 et c2 occupent la même place mémoire qui est la moitié basse de w1 et un quart de l.
b3, s3 et c3 occupent la même place mémoire qui est la moitié haute de w1 et le quart haut de l.
---------l---------
----wO--- ----w1---
-s3-
-b0- -b1- -b2- -b3-
-c0- -c1- -c2- -c3-
Le programme précédent écrit :
-1
65535 -1
255 255 255 255/-1
530
530 0
18 2 0 0/0
577
577 0
65 2 0 0/0
65536577
577 1000
65 2 232 3/3
a.l:=-1 met les 32 bits de l à 1.
w0 a ses 16 bits à 1, il vaut donc 216-1=65535.
w1 a ses 16 bits à 1, il vaut donc -1.
b0, b1, b2 et b3 ont leur 8 bits à 1. Ils valent donc 28-1=255.
s3 a ses 8 bits à 1, il vaut donc -1.
530=0*65336+530=0*224+0*216+2*28+ 18
Le code ASCII de 'A' est 65 et 65+2*256=577.
1000=3*256+232 et 1000*65536+577=65536577