Академический Документы
Профессиональный Документы
Культура Документы
Pensez à structurer l’implémentation, à mettre des commentaires et à passer les arguments par référence en
les protégeant (const) si besoin. On écrira l’implémentation dans des fichiers séparés.
1) Ecrire une classe vecteur ayant pour données membres privées la dimension du vecteur : int dim et
un tableau de float : float * val ayant :
• un destructeur
• une fonction membre val(i) d’accès à la i ème valeur (i=1,n) permettant la lecture et l’écriture
• des fonctions externes à la classe permettant de faire la somme, la différence de deux vecteurs ainsi
que le produit d’un scalaire par un vecteur
• une fonction réalisant le produit scalaire de deux vecteurs et une fonction calculant la norme d’un
vecteur
- Ecrire l’implémentation des membres de classes dans un fichier séparé et les définitions dans un fichier
entête.
- Afin de tracer le comportement des constructeurs, inclure dans toutes les fonctions une impression indiquant
le passage par la fonction.
3) Ecrire dans le même esprit une classe matrice utilisant un tableau simple float * val , le rangement
s’opérant par colonne. Prévoir les principaux constructeurs, l’accès à l’élément (i,j) ainsi que des fonctions
d’accès renvoyant un pointeur sur le premier élément d’une ligne et sur le premier élément d’une colonne,
une fonction d’impression.
4) Ecrire un produit matrice × vecteur le plus rapide possible (tester avec la fonction time). Comparer
en particulier, une version fondée sur l’opérateur d’accès (i,j) et celle fondée sur un accès par pointeur et
un algorithme adapté aux pointeurs (déplacement séquentiel) : si p désigne un pointeur p++ incrémente le
pointeur de 1 et donne un pointeur sur l’élément suivant.
1
Correction
classe vecteur
//===========================================================================
// class vecteur (header file)
//===========================================================================
// classe permettant de manipuler des vecteurs mathématiques
// s’appuie sur un tableau de double
//
// principales fonctionnalités :
// - constructeur par défaut, dimension et valeur et par copie
// - accès en lecture et écriture à un élément
// - impression du vecteur
// - somme et différence de deux vecteurs (externes à la classe)
// - produit par un scalaire (externe à la classe)
// - produit scalaire et norme euclidienne (externe à la classe)
//===========================================================================
#ifndef vecteurH
#define vecteurH
// fichiers ent^
etes système
#include <iostream>
//---------------------------------------------------------------------------
// class vecteur (définition)
//---------------------------------------------------------------------------
class vecteur
{
private :
int dim_; // dimension du vecteur
double * val_; // tableau des valeurs
public :
//constructeurs/destructeurs
vecteur(): dim_(0),val_(NULL) {} //constructeur par défaut
vecteur(int d,double v=0.); //constructeur dimension et val. initiale
vecteur(const vecteur &V); //constructeur par copie
~vecteur(); //destructeur
//accès à un élément
double & val (int ) const; //acces au i ème élément, i=1 à dim
double & val2(int) const; //acces robuste
int dim() const; //retourne la dimension du vecteur
//impression
void print(); //impression sur l’unité standard (cout)
};}
//---------------fin de définition de la classe vecteur-----------------------
//utilitaire
//----------
void coherence_dim(const vecteur &,const vecteur &); //test de cohérence de la dimension de deux vecteurs
//===========================================================================
// class vecteur (implementation file)}
//===========================================================================
// voir header pour la définition de la classe vecteur}
//---------------------------------------------------------------------------
//fichiers ent^
etes
#include "vecteur.h"
// fichiers ent^
etes système
#include <iostream>
//constructeurs/destructeurs
//-------------------------
vecteur::vecteur(int d,double v) //constructeur dimension et val. initiale
{//suivi
#ifdef debug
cout<<"vecteur : constructeur (int d,double v)\n";
#endif
dim_=d;val_=NULL;
if(d<=0) return; //aucune allocation, vecteur vide
val_=new double[dim_];
for(int i=0;i<dim_;i++) val_[i]=v; //affectation
}
2
vecteur::vecteur(const vecteur &V) //constructeur par copie
{//suivi
#ifdef debug
cout<<"vecteur : constructeur copie(const vecteur &V)\n";
#endif
dim_=V.dim_;val_=NULL;
if(dim_<=0) return; //aucune allocation, vecteur vide
val_=new double[dim_];}
for(int i=0;i<dim_;i++) val_[i]=V.val_[i]; //recopie
}
vecteur::~vecteur() //destructeur
{//suivi
#ifdef debug
cout<<"vecteur : destructeur\n";
#endif
if(val_!=NULL) delete [] val_; //libération mémoire
}
//accès à un élément
//------------------
double & vecteur::val(int i) const //acces au i ème élément, i=1 à dim
{return val_[i-1];}
//impression
//----------
void vecteur::print() //impression sur l’unité standard (cout)
{cout<<"vecteur de dimension "<<dim_<<endl;
for(int i=0;i<dim_;i++) cout<<val_[i]<<" ";
cout<<endl;
}
vecteur diff (const vecteur &V1, const vecteur &V2) //différence de deux vecteurs
{coherence_dim(V1,V2);
vecteur R(V1); //création du résultat avec copie de V1
for(int i=1;i<=V1.dim();i++) R.val(i)-=V2.val(i);
return R;
}
vecteur produit(const vecteur &V, double x) //produit d’un vecteur par un scalaire
{ vecteur R(V); //création du résultat avec copie de V
for(int i=1;i<=V.dim();i++) R.val(i)*=x;
return R;
}
//versions rapides
//les "fast" version n’appellent pas le test sur la dimension
//et font un accès par pointeur (gain de 25%)
vecteur fast_somme(const vecteur &V1, const vecteur &V2) //somme de deux vecteur
{vecteur R(V1); //création du résultat avec copie de V1
double *pR=&R.val(1);
double *p2=&V2.val(1);
for(int i=1;i<=V1.dim();i++,pR++,p2++) (*pR)+=(*p2);
return R;
}
vecteur fast_diff (const vecteur &V1, const vecteur &V2) //différence de deux vecteurs
{vecteur R(V1); //création du résultat avec copie de V1
double *pR=&R.val(1);
double *p2=&V2.val(1);
for(int i=1;i<=V1.dim();i++,pR++,p2++) (*pR)-=(*p2);
return R;
}
vecteur fast_produit(const vecteur &V, double x) //produit d’un vecteur par un scalaire
{vecteur R(V); //création du résultat avec copie de V
double *pR=&R.val(1);
for(int i=1;i<=V.dim();i++,pR++) (*pR)*=x;
return R;
}
3
}
//utilitaire
//----------
void coherence_dim(const vecteur &V1,const vecteur &V2) //test de cohérence de la dimension de deux vecteurs
{if(V1.dim()==V2.dim()) return;
cout<<"somme de deux vecteurs : dimensions incohérentes "<<V1.dim()<<" et "<<V2.dim();
exit(1);
}
classe matrice
//===========================================================================
// class matrice (header file)
//===========================================================================
// classe permettant de manipuler des matrices
// s’appuie sur un tableau de double (rangement par colonne, idem Fortran)
//
// principales fonctionnalités :
// - constructeur par défaut, dimension et valeur et par copie
// - accès en lecture et écriture à un élément
// - impression du vecteur
// - somme et différence de deux vecteurs (externes à la classe)
// - produit par un scalaire (externe à la classe)
//===========================================================================
#ifndef matriceH
#define matriceH
// fichiers ent^
etes système
#include <iostream>
//fichiers ent^
ete
#include "vecteur.h"
//---------------------------------------------------------------------------
// class matrice (définition)
//---------------------------------------------------------------------------
class matrice
{
private :
int dim_l_,dim_c_; // dimension de la matrice matrice
double * val_; // tableau des valeurs
public :
//constructeurs/destructeurs
matrice(): dim_l_(0),dim_c_(0),val_(NULL) {} //constructeur par défaut
matrice(int ,int ,double v=0.); //constructeur dimensions et val. initiale
matrice(const matrice &); //constructeur par copie
~matrice(); //destructeur
//accès à un élément
double & val (int i,int j) const; //acces au terme(i,j), i=1 à dim_l, j=1 à dim_c
double & val2(int i,int j) const; //acces robuste
int dim_l() const; //retourne la dimension du matrice
int dim_c() const; //retourne la dimension du matrice
//impression
void print(); //impression sur l’unité standard (cout)
};}
//---------------fin de définition de la classe matrice-----------------------
matrice somme(const matrice &, const matrice &); //somme de deux matrice
matrice diff (const matrice &, const matrice &); //différence de deux matrices
matrice produit(const matrice &, double); //produit d’un matrice par un scalaire
vecteur produit(const matrice & ,const vecteur & ); //produit matrice x vecteur
vecteur fast_produit(const matrice & ,const vecteur & ); //produit matrice x vecteur (fast version)
//utilitaire
//----------
void coherence_dim(const matrice &,const matrice &); //test de cohérence de la dimension de deux matrices
//===========================================================================
// class matrice (implementation file)
//===========================================================================
// voir header pour la définition de la classe matrice
//---------------------------------------------------------------------------
//fichiers ent^
etes
#include "matrice.h"
// fichiers ent^
etes système
4
#include <iostream>
//constructeurs/destructeurs
//-------------------------
matrice::matrice(int dl,int dc,double v) //constructeur dimension et val. initiale
{//suivi
#ifdef debug
cout<<"matrice : constructeur (int dl,int dc,double v)\n";
#endif
dim_l_=dl;dim_c_=dc;val_=NULL;
int d=dl*dc;
if(d<=0) return; //aucune allocation, matrice vide
val_=new double[d];
for(int k=0;k<d;k++) val_[k]=v; //affectation
}
matrice::~matrice() //destructeur
{//suivi
#ifdef debug
cout<<"matrice : destructeur";
#endif
if(val_!=NULL) delete [] val_; //libération mémoire
}
//accès à un élément
//------------------
double & matrice::val(int i, int j) const //acces à l’élément (i,j)
{return val_[(j-1)*dim_l_+i-1];}
//impression
//----------
void matrice::print() //impression sur l’unité standard (cout)
{cout<<"matrice de dimensions "<<dim_l_<<" x "<<dim_c_<<endl;
for(int i=1;i<=dim_l_;i++)
{for(int j=1;j<=dim_c_;j++) cout<<val(i,j)<<" ";
cout<<endl;
}
cout<<endl;
}
matrice somme(const matrice &V1, const matrice &V2) //somme de deux matrice
{coherence_dim(V1,V2);
matrice R(V1); //création du résultat avec copie de V1
for(int i=1;i<=V1.dim_l();i++)
for(int j=1;j<=V1.dim_c();j++)
R.val(i,j)+=V2.val(i,j);
return R;
}
matrice diff (const matrice &V1, const matrice &V2) //différence de deux matrices
{coherence_dim(V1,V2);
matrice R(V1); //création du résultat avec copie de V1
for(int i=1;i<=V1.dim_l();i++)
for(int j=1;j<=V1.dim_c();j++)
R.val(i,j)-=V2.val(i,j);
return R;
}
matrice produit(const matrice &V, double x) //produit d’un matrice par un scalaire
{ matrice R(V); //création du résultat avec copie de V
for(int i=1;i<=V.dim_l();i++)
for(int j=1;j<=V.dim_c();j++) R.val(i,j)*=x;
return R;
}
matrice fast_somme(const matrice &V1, const matrice &V2) //somme de deux matrice
{matrice R(V1); //création du résultat avec copie de V1
double *pR=&R.val(1,1);
double *p2=&V2.val(1,1);
int lg=V1.dim_l()*V1.dim_c();
for(int k=0;k<lg;k++,pR++,p2++) (*pR)+=(*p2);
return R;
}
matrice fast_diff (const matrice &V1, const matrice &V2) //différence de deux matrices
5
{matrice R(V1); //création du résultat avec copie de V1
double *pR=&R.val(1,1);
double *p2=&V2.val(1,1);
int lg=V1.dim_l()*V1.dim_c();
for(int k=0;k<lg;k++,pR++,p2++) (*pR)-=(*p2);
return R;
}
matrice fast_produit(const matrice &V, double x) //produit d’un matrice par un scalaire
{matrice R(V); //création du résultat avec copie de V
double *pR=&R.val(1,1);
int lg=V.dim_l()*V.dim_c();
for(int k=0;k<lg;k++,pR++) (*pR)*=x;
return R;
}
//utilitaires
//-----------
void coherence_dim(const matrice &V1,const matrice &V2) //test de cohérence de la dimension de deux matrices
{if(V1.dim_l()==V2.dim_l() && V1.dim_c()==V2.dim_c()) return;
cout<<"somme de deux matrices : dimensions incohérentes ";
cout<<V1.dim_l()<<"x"<<V1.dim_c()<<" et "<<V2.dim_l()<<"x"<<V2.dim_c();
exit(1);
}
Programme principal
//===========================================================================
// TP2 Introduction aux classes d’objets
//===========================================================================
// classe vecteur et matrice
//fichiers d’ent^
etes
//------------------
#include "vecteur.h"
#include "matrice.h
#include <iostream>
#include <time.h>
using namespace std;
//programme principal
//-------------------
int main( )
//test impression
cout<<"V1 ";V1.print();
cout<<"V2 ";V2.print();
cout<<"V3 ";V3.print();
cout<<"V4 ";V4.print();
//test acces
V2.val(1)=1.;V2.val(2)=2.;V2.val(3)=3.;
cout<<"acces : V2 ";V2.print();
//test destructeur
vecteur *pV5=new vecteur(V2);
pV5->print();
delete pV5;
6
cout<<"somme V6=V2+V3 ";V6.print();
V7=diff(V2,V3);
cout<<"différence V7=V2-V3 ";V7.print();
V8=produit(V2,5);
cout<<"produit V8=5*V2 ";V8.print();
cout.flush();
time_t t0,t1;
//test de vitesse
vecteur U(1000,1);
vecteur V(1000,2);
vecteur W(1000);
t0=time(NULL);
for(int k=0;k<800000;k++) W=somme(U,V);
t1=time(NULL);
cout<<"\ntemps pour la somme = "<<t1-t0;
cout.flush();
t0=time(NULL);
for(int k=0;k<800000;k++) W=fast_somme(U,V);
t1=time(NULL);
cout<<"\ntemps pour la somme = "<<t1-t0<<endl;
//test de vitesse
//===============
vecteur U(100,1);
vecteur V(100,0);
matrice I(100,100,1);
t0=time(NULL);
for(int k=0;k<50000;k++) V=produit(I,U);
t1=time(NULL);
cout<<"\ntemps pour le produit matrice vecteur = "<<t1-t0<<endl;
cout.flush();
t0=time(NULL);
for(int k=0;k<50000;k++) V=fast_produit(I,U);
t1=time(NULL);
cout<<"\ntemps pour le fast produit matrice vecteur = "<<t1-t0<<endl;
//fin du programme
return 0;
}
//============================= F I N ===================================
Résultats du programme
V1 vecteur de dimension 0
V2 vecteur de dimension 3
0 0 0
V3 vecteur de dimension 3
1 1 1
V4 vecteur de dimension 3
1 1 1
acces : V2 vecteur de dimension 3
7
1 2 3
vecteur de dimension 3
1 2 3
somme V6=V2+V3 vecteur de dimension 3
2 3 4
différence V7=V2-V3 vecteur de dimension 3
0 1 2
produit V8=5*V2 vecteur de dimension 3
5 10 15
somme V6=V2+V3 vecteur de dimension 3
2 3 4
différence V7=V2-V3 vecteur de dimension 3
0 1 2
produit V8=5*V2 vecteur de dimension 3
5 10 15
temps pour la somme = 22
temps pour la fast somme = 14
Id matrice de dimensions 3 x 3
1 0 0
0 1 0
0 0 1
A matrice de dimensions 3 x 3
1 0 0
0 1 0
0 0 1
somme B=A+Id matrice de dimensions 3 x 3
2 0 0
0 2 0
0 0 2
différence B=A-Id matrice de dimensions 3 x 3
0 0 0
0 0 0
0 0 0
produit B=5*Id matrice de dimensions 3 x 3
5 0 0
0 5 0
0 0 5
fast somme B=A+Id matrice de dimensions 3 x 3
2 0 0
0 2 0
0 0 2
fast différence B=A-Id matrice de dimensions 3 x 3
0 0 0
0 0 0
0 0 0
fast produit B=5*Id matrice de dimensions 3 x 3
5 0 0
0 5 0
0 0 5
matrice vecteur R=A*V2 vecteur de dimension 3
1 2 3
fast matrice vecteur R=A*V2 vecteur de dimension 3
1 2 3
temps pour le produit matrice vecteur = 14
temps pour le fast produit matrice vecteur = 5
On remarquera que les versions ”fast” (programmation par pointeur et algorithmes séquentiels) sont plus
rapides. En particulier, le produit matrice x vecteur est 3 fois plus rapide. Cela résulte du fait que dans la ver-
sion normale du produit matrice x vecteur, comme on accède à un élément (i,j) via la formule (j-1)*dim l+i-
1, on a à faire à chaque étape 4 additions et 2 multiplications contre 1 addition et une multiplication dans
la version rapide (les incréments de pointeurs ont été négligés).