Telechargé par arnaud olivier

TDJava

publicité
Université Paris Diderot
MASS L2
JAVA
Année 2007-2008
TD n◦4 - Correction
Partiel 1b
Attention à bien rendre l’énoncé avec votre copie, et à bien indiquer votre nom sur toutes
les pages. Vous pourrez traiter les exercices dans l’ordre de votre choix. Les questions ((bonus))
étant plus difficiles, il est conseillé de les garder pour la fin.
Exercice 1
1. On considère la classe suivante :
class Carre {
private double cote; // champs/attribut
public Carre() // constructeur (sans argument)
{
cote=10;
}
public double getCote() // accesseur
{
return cote;
}
public Carre(double c) // constructeur
{
if (c >= 0)
cote=c;
else
cote=0;
}
public String toString() // méthode
{
return ¨Carré de coté ¨+cote;
}
public void setCote(double c) // modifieur
{
if (c >= 0)
cote = c;
}
}
1
Indiquez à côté de chaque // à quoi correspond la ligne (accesseur. . .).
2. On considère le code suivant :
public static void main(String[] argd)
{
Carre c1 = new Carre();
Deug.println(c1.getCote()); // 10 : lors de l’appel
// à new, le constructeur sans argument est appelé.
Deug.println(c1); // carré de coté 10 : il y a un appel
// automatique à toString() pour convertir c1 en chaine de caractère
Carre c2 = c1; //c2 et c1 désignent maintenant le m^
eme objet
Deug.println(c2.getCote()); // 10
c1.setCote(3); //modifie l’objet référencé par c1 et c2
c2.setCote(4); //idem
Deug.println(c2.getCote()); // 4 : le résultat de la
//dernière modification
Deug.println(c1.getCote()); // 4 : idem
c2.setCote(-3);
Deug.println(c2.getCote()); // 4 : le modifieur ne fait rien
// si on lui passe un entier négatif : la valeur de cote
// reste inchangée
c2 = new Carre(5); //on créé un nouvel objet de type Carre,
//et c2 référence cet objet.
//On n’a pas touché à c1, qui référence encore
//l’ancien objet.
Deug.println(c1.getCote()); // 4
Deug.println(c2.getCote()); // 5
int i = 0;
int j = i; // int est un type primitif : i et j ne sont
// pas des références, mais des valeurs. Après cette ligne
// j vaut 0, i vaut 0, mais i et j ne sont plus reliés
// d’aucune façon.
j++; // c’est-à-dire j=j+1
Deug.println(i); // 0
2
Deug.println(j); // 1
}
Indiquez (sans justifier) à côté de chaque ligne commençant par Deug.println() le
résultat affiché.
3
Exercice 2
1. Écrire une méthode int nbPos(int[] tab) renvoyant le nombre d’entiers positifs dans
le tableau passé en argument.
Correction :
static int nbPos(int[] tab)
{
int res=0;
for (int i=0; i<tab.length; i++)
if (tab[i]>=0) res=res+1;
return res;
}
2. Écrire une méthode int[] nPremier(int n) renvoyant un tableau constitué des n + 1
premiers naturels. Par exemple, nPremier(5) devra renvoyer {0, 1, 2, 3, 4, 5}.
Correction :
Dans toutes les méthodes, il faut commencer par créer un tableau de la bonne taille, puis trouver
comment le (( remplir )).
int[] nbPos(int n)
{
int[] res=new int[n+1];
for (int i=0; i<res.length; i++)
res[i]=i;
return res;
}
3. Écrire une méthode int[] sansPremier(int[] tab) renvoyant le tableau passé en argument auquel on a enlevé le premier élément.
Correction :
int[] sansPremier(int[] tab)
{
int[] res=new int[tab.length-1];
for (int i=0; i<res.length; i++)
res[i]=tab[i+1]; //attention au décallage d’indice.
return res;
}
4. (bonus) Écrire une méthode int[] intercalle(int[] tab) renvoyant le tableau passé
en argument, auquel on a intercallé des zéros. Par exemple, intercalle({2, 3, 5})
devra renvoyer {2, 0, 3, 0, 5}.
Correction :
Il faut voir tout d’abord que la taille du tableau renvoyée doit être 2tab.length − 1.
Ensuite, il faut faire assez attention au remplissage, et ne pas s’emmeler les pinceaux dans les
indices. Une bonne question à se poser, qui permet de trouver ses erreurs, est de se demander si
pour les valeurs extrèmes des boucles, on n’est pas en train de sortir des bornes du tableau.
Il faut aussi vérifier qu’on a bien récupéré tous les éléments du tableau de départ.
4
int[] intercalle(int[] tab)
{
int[] res=new int[2*tab.length-1];
for (int i=0; i<res.length; i++)
if (i%2==0) res[i]=tab[i/2];
else res[i]=0;
return res;
}
pour i = res.length − 1, les appels res[i] et tab[i/2] sont encore corrects.
ou bien
int[] intercalle(int[] tab)
{
int[] res=new int[2*tab.length-1];
for (int i=0; i<res.length; i++)
res[i]=0;
for (int i=0; i<tab.length; i++)
res[2*i]=tab[i];
return res;
}
ici, pour i = tab.length − 1, 2i = 2tab.length − 2 = res.length − 1, et res[] désigne donc bien le
dernier élément de res.
Exercice 3
Que fait la méthode suivante ?
public static String maMethode(String s)
{
String res=¨¨;
for (int i=0; i<s.length(); i++)
{
char c = s.charAt(i);
if (c == ’a’)
return res;
res+=c;
}
return ¨¨;
}
Correction :
Cette méthode retourne la chaine vide si la chaine passée en argument ne contient pas de ’a’. Sinon,
elle renvoie la partie de la chaine située avant le premier ’a’. Quelques exemples
¨bonjour¨ → ¨¨
¨ola¨ → ¨ol¨
¨good day¨ → ¨good d¨
5
Exercice 4 Nous allons dans cette exercice écrire une petite classe permettant de gérer des
polynômes. Nous nous limiterons à des polynômes de degré maximal 5. Un polynôme sera
représenté par un tableau de double de taille 6. Par exemple, le polynôme 2.5X 3 + 2X 2 + 0.5
sera représenté par le tableau suivant : {0.5, 0, 2, 2.5, 0, 0}.
1. Écrire une classe Polynome, contenant un champ privé tab de type tableau de rééls. Dans
quel fichier doit être située cette classe ?
Correction :
class Polynome
{
private double[] tab;
}
cette classe doit être située dans le fichier Polynome.java .
Le tableau tab va permettre de stocker les coefficients du polynôme. Depuis les méthodes de la
classe, on va le désigner par this.tab, ou seulement tab.
2. Écrire un constructeur sans argument permettant de créer le Polynôme nul (c’est-à-dire
dont tous les coefficients sont nuls).
Correction :
il faut penser à définir le tableau tab, qui a seulement été déclaré dans la première question : par
défaut, tab est une référence nulle : il faut donc créer un nouveau tableau de la taille voulu, et
faire en sorte que tab le référence. Si l’on omet de faire celà, un appel du type tab[0] va provoquer
une erreur à l’éxécution.
Règle générale : si vous utilisez un tableau avant d’avoir déclaré sa taille, c’est surement qu’il y a
un problème quelquepart. . .
public Polynome()
{
tab=new double[6];
for (int i=0; i<6; i++)
tab[i]=0;
}
3. Écrire une méthode setCoeff(int coeff, double valeur) permettant de mettre le coefficient du monôme de degré coeff à la valeur indiquée.
Correction :
void setCoeff(int coeff, double valeur)
{
if (coeff>=0 && coeff<6)
tab[coeff]=valeur;
}
il n’y a pas lieu de déclarer un nouveau Polynome ou un nouveau tableau : on est en train de
travailler sur le polynôme courant (this).
Voice un exemple d’utilisation de la classe Polynome définie jusqu’à présent :
public static void main(String[] argd)
{
Polynome p = new Polynome();
//créé un polyn^
ome nul en appelant le constructeur par défaut.
6
p.setCoeff(0, 3.5);
p.setCoeff(1, 2);
//le polyn^
ome p représente maintenant 2X+3.5
}
4. Écrire une méthode Polynome somme(Polynome p) renvoyant un polynôme égale à la
somme du polynôme et de p.
Correction :
ce sont les champs tab de chacun des polynômes que l’on doit additionner. p[i], this[i], ou pire
P olynome[i] n’ont pas de sens.
Polynome somme(Polynome p)
{
Polynome res = new Polynome();
for (int i=0; i<6; i++)
res.tab[i]=tab[i]+p.tab[i];
return res;
}
5. Écrire une méthode int degre() renvoyant le degré du polynôme (par convention, on
renverra −1 s’il s’agit du polynôme nul).
Correction :
On parcours les coefficients dans le sens des degrés décroissants. Dès qu’on en rencontre 1 non nul,
nous avons le degré.
int degre()
{
for (int i=5; i>=0; i--)
if (tab[i]!=0) return i;
return -1;
}
Exemple : si p représente 3X + 1, p.tab vaut {1, 3, 0, 0, 0, 0}.
On parcours les coefficients dans le sens décroissant :
6→0
5→0
4→0
3→0
2 → 2 6= 0
le degré est donc 3.
Si tous les coefficients sont nuls, on renvoie 0.
6. Écrire une méthode double eval(double x) renvoyant l’évaluation du polynôme en x.
On rappelle que xn peut s’obtenir à l’aide de la fonction M ath.pow(x, n);.
Correction :
7
double eval(double x)
{
int res=0;
for (int i=0; i<6; i++)
res+=tab[i]*Math.pow(x, i);
return res;
}
7. Écrire une méthode String toString() renvoyant une chaı̂ne de caractères décrivant
le polynôme. Par exemple, pour le polynôme donné en exemple, on souhaiterait qu’elle
retourne ¨2.5 X^3 + 2.0 X^2 + 0.5¨
Correction :
Il faut être attentif
– à l’ordre
– à ne pas afficher les monômes nuls
– à ne pas avoir un + en trop à la fin ou au début.
String toString()
{
String res=¨¨;
boolean premier=true;
for (int i=5; i>=0; i--)
if (tab[i]!=0)
{
if (premier)
{
res+=tab[i]+¨ X^¨+i;
premier = false;
}
else
res+=¨ + ¨+tab[i]+¨ X^¨+i;
}
return res;
}
8. (bonus) Si M ath.pow(x, n); utilise n − 1 multiplications de réels, combien de multiplications sont-elles effectuées lors de l’appel de eval sur un polynôme de degré n ?
Correction :
pour calculer la valeur du monome de degré i, on effectue i − 1 multiplications pour calculer
M ath.pow(x, i);, et une de plus pour multiplier par le coefficient. Il faut donc i multiplications.
Pour l’ensemble des monômes, il faudra donc
n
X
i=
i=1
n(n − 1)
2
mutiplications, ce qui est de l’ordre de n2 .
8
9. (bonus) La méthode de Horner permet de calculer plus rapidement la valeur d’un polynôme en un point.
Soit à calculer −2X 3 + 2.5X 2 + 2X + 0.5 en x.
On remarque que −2X 3 + 2.5X 2 + 2X + 0.5 = 0.5 + X(2 + X(2.5 + X(−2)))
Utiliser cette remarque pour écrire une méthode double horner(double x) renvoyant le
même résultat que eval mais n’utilisant que deg(P ) multiplications.
Correction :
double horner(double x)
{
double res=0;
for (int i=tab.length-1; i>=0; i--)
{
res=res*x+tab[i];
}
}
cette méthode n’utilise que n multiplications, ce qui est un gain substanciel.
9
Téléchargement