A3P: Sujet du TP 2.1
ESIEE Engineering, Denis BUREAU, 1213v1.

Attention ! Le sujet peut être modifié jusqu'à la veille du TP.

1  Les objectifs

Être capable de réaliser sur machine des programmes ne mettant pas en oeuvre des instances. Comprendre l'importance des problèmes de débordement arithmétique et de précision. Savoir utiliser les tests unitaires dans BlueJ. Lire la version PDF de ce sujet et n'utiliser la version web que pour cliquer sur les liens.
Attention ! Ce sujet est long, mais les 3 exercices sont faits pour être traités progressivement, ce qui explique les différentes versions, et de nombreux tests sont fournis pour permettre un travail personnel avec une auto-évaluation. Donc, aucune raison de ne pas terminer seul ce TP.

2  Factorielle et problèmes avec les entiers

Charger le projet sujtp3.jar et écrire les méthodes suivantes dans la classe Factorielle. Pour pouvoir tester facilement les méthodes suivantes, déclarez-les toutes en static, afin de ne pas être obligés de créer un objet avant de lancer une méthode, et respectez les noms indiqués.
  1. fact1() :
    Écrivez en Java (dans la classe Factorielle) la fonction factorielle non récursive, mais avec une amélioration : retournez systématiquement -1 si le paramètre est négatif. (Rappel: 0! = 1)
    Essayez 6; ça fait bien 720 ?
  2. Dans la classe FactorielleTest, décommentez (menu Edit, Uncomment) toutes les lignes de la méthode testAfact1() sauf la dernière ligne commentée.
    Compilez; s'il y a des erreurs, corrigez votre code pour qu'il corresponde à ce qu'attend la classe de test. Si le bouton à gauche Run Tests n'apparaît pas, menu Tools/Preferences/Miscellaneous/Show unit testing tools). Lancer testAfact1(). Tout est vert ? Sinon, voir l'encadré ci-dessous.
  3. monTest1() :
    Écrivez en Java (dans la classe Factorielle) une procédure de test qui affiche la factorielle de tous les nombres compris entre ses 2 paramètres, sous la forme 3! = 6 (par exemple, pour la factorielle de 3)
    Questions : Ajoutez dans fact1() un test pour ne pas accepter un paramètre supérieur au maximum trouvé précédemment. Retournez -1 dans ce cas. Décommentez le dernier test de testAfact1(). Retestez.
  4. Dans la classe FactorielleTest, décommentez la ligne de la méthode testBmonTest1().
    Compilez; s'il y a des erreurs, corrigez votre code pour qu'il corresponde à ce qu'attend la classe de test. Lancez testBmonTest1(). Tout est vert ? Sinon, voir l'encadré ci-dessous.


  5. Dans BlueJ, en cas d'échec sur un test, cliquez sur la première ligne non "verte", interprétez le message d'erreur, puis cliquez sur le bouton Show Source pour savoir ce qui a été testé. Activez également l'affichage des numéros de ligne (Tools/Preferences/Editor/Display line numbers). Il peut aussi être utile d'utiliser le "Code Pad" (menu View) pour essayer interactivement des expressions Java.




  6. fact2() :
    Pour essayer d'aller plus loin que 12!, nous allons utiliser un nouveau type primitif entier qui stocke ses nombres non plus sur 4 mais sur 8 octets (alors pourquoi pas le type double ?) : le mot java est long.
    Dupliquez la méthode fact1() (dans la classe Factorielle) en la changeant de nom, et remplacez uniquement là où il le faut int par long. Les constantes littérales se terminent par L (ex: -1L).
    Pensez-vous que fact2() pourra calculer jusqu'à 100, 1000, plus ?
    Soyons raisonnables : ayant doublé le nombre d'octets, nous supposerons dans un premier temps que le maximum ne peut pas plus que doubler. Modifiez-le dans fact2().
  7. Dans la classe FactorielleTest, décommentez toutes les lignes de la méthode testCfact2().
    Compilez; s'il y a des erreurs, corrigez votre code pour qu'il corresponde avec ce qu'attend la classe de test. Run Tests : Tout est vert ?
  8. monTest2() :
    Recopiez la procédure monTest1() et modifiez-la pour qu'elle appelle fact2() au lieu de fact1().
    Questions :
  9. Dans la classe FactorielleTest, décommentez la ligne de la méthode testDmonTest2().
    Compilez, Testez. Tout est vert ?
  10. Pour essayer d'aller plus loin que 20!, nous allons utiliser un nouveau type entier (objet) qui stocke ses nombres non plus sur 4 ou sur 8 octets, mais dans une String de longueur pratiquement illimitée : le nom de cette classe est BigInteger.
    Dupliquez la méthode fact2() (dans la classe Factorielle) en la changeant de nom, et remplacez les long par des BigInteger.
    Il va falloir faire un certain nombre de modifications car nous remplaçons un type primitif par un type objet :
    - repérez le paquetage de BigInteger (voir javadoc); cela servira pour la compilation
    - utilisez le BigInteger de valeur 1 (voir javadoc)
    - utilisez la bonne méthode pour prendre l'opposé (voir javadoc)
    - utilisez la bonne méthode pour convertir un int en BigInteger (voir javadoc, sachant qu'un int est automatiquement converti en long si nécessaire)
    - utilisez la bonne méthode pour multiplier (voir javadoc)
    Pensez-vous que fact3() pourra calculer jusqu'à 100, 1000, plus ?
    Soyons déraisonnables : supprimons la borne supérieure du test dans fact3() et découvrons des factorielles rarement calculées.
  11. Dans la classe FactorielleTest, décommentez toutes les lignes de la méthode testEfact3().
    Compilez, Testez. Tout est vert ?
  12. monTest3() :
    Recopiez la procédure monTest2() et modifiez-la pour qu'elle appelle monTest3() au lieu de monTest2().
    Questions :
  13. Dans la classe FactorielleTest, décommentez la ligne de la méthode testFmonTest3().
    Compilez, Testez. Tout est vert ?

3  Racine carrée et problèmes avec les réels

       (D'après un exercice de Jean-Claude GEORGES) Affichez le sujet en PDF (version imprimable)
Écrivez les méthodes suivantes dans la classe RacineNewton :
  1. environ1() :
    Pour pouvoir comparer des nombres réels, comme nous ne pouvons pas utiliser l'opérateur ==, on définira une fonction booléenne environ1() qui comparera ses 2 paramètres réels x et y à e près (|x-y| < e ?) et on utilisera environ1(x,y) au lieu de x == y.
    On définira e en CONSTANTE de classe (qu'on choisira égale à 10-6).
  2. Dans la classe RacineTest, décommentez toutes les lignes de la méthode testAenviron1().
    Compilez, Testez. Tout est vert ?
  3. racine1() :
    Cette fonction doit calculer la racine carrée d'un nombre positif (sans utiliser Math.sqrt()) selon l'algorithme de Newton, c'est-à-dire : si on suppose que r est une valeur approchée (même très mauvaise) de a, alors Newton a montré que [1/2](r+[a/r]) est une meilleure valeur approchée.
    On peut donc en théorie se rapprocher aussi près que l'on veut de la valeur ëxacte" de la racine carrée ; essayons de le vérifier à e près ; on arrêtera donc la boucle lorsque l'écart entre r2 et a sera inférieur à e.
    AIDE : Toute valeur initiale est possible pour r, par exemple [a/2] ou 1 ou ...
  4. Dans la classe RacineTest, décommentez toutes les lignes de la méthode testBracine1().
    Compilez, Testez. Tout est vert ?
    Testez encore votre fonction avec au moins les valeurs suivantes :
    1E-6 : ça fait bien 0.001000 ? Pourquoi ?
    1E-20 : ça fait bien 1E-10 ? Pourquoi ?
    1E11 : ça fait bien 316227.766017 ? Pourquoi ? (oscillations ?)
  5. environ2() :
    Compte tenu des problèmes précédents, écrivez une nouvelle fonction booléenne qui comparera ses 2 paramètres réels x et y en tenant compte de l'ordre de grandeur de x ou y (|[(x-y)/x]| < e ?) Cette formule n'est correcte que si x n'est pas trop proche de 0). Dans le cas contraire, il faut donc diviser par y. Si les deux sont très proches de 0, on peut directement retourner vrai.
    On considérera que x est assimilable à 0 si |x| < 10-300. Pour cela, définir cette valeur particulière en CONSTANTE de classe et définir une fonction booléenne zero() qui retournera vrai si son paramètre réel est assimilable à 0.
  6. Dans la classe RacineTest, décommentez toutes les lignes de la méthode testCenviron2().
    Compilez, Testez. Tout est vert ?
  7. racine2() :
    Recopiez la fonction racine1() en changeant son nom et modifiez-la pour qu'elle appelle environ2() au lieu de environ1(). D'autre part, si x est assimilable à 0, Öx = 0.0.
  8. Dans la classe RacineTest, décommentez toutes les lignes de la méthode testDracine2().
    Compilez, Testez. Tout est vert ?
    Est-ce correct pour les 3 valeurs problématiques du 3.4 ci-dessus ?

4  Projet "Lines" (A COMMENCER EN TP ET A TERMINER EN TRAVAIL PERSONNEL)

Cet exercice va consister à créer une nouvelle classe, indépendante, permettant de représenter une droite dans le plan, puis à comparer 2 droites (d'équations a1x+b1y+c1=0 et a2x+b2y+c2=0).
Rappels mathématiques :
- 2 droites sont orthogonales si le produit scalaire des vecteurs directeurs est nul (a1a2+b1b2=0)
- 2 droites sont colinéaires si elles ont le même coefficient directeur (-[(b1)/(a1)] = -[(b2)/(a2)] si a1 0 et a2 0) ou mieux, si le déterminant principal est nul.
- 2 droites peuvent être confondues sans avoir nécessairement a1=a2 et b1=b2 et c1=c2, il suffit que les deux déterminants secondaires soient nuls.
- x1y2 = x2y1 remplace avantageusement [(x1)/(y1)] = [(x2)/(y2)]

4.1  Créer un nouveau projet

Créer dans le répertoire tp3, préalablement créé,  un nouveau projet BlueJ de nom Lines.

4.2  Créer une nouvelle classe

Définir une classe Line, en la documentant au fur et à mesure, répondant aux spécifications suivantes :

4.2.1  Version 1




4.2.2  Version 2

4.2.3  Version 3

4.2.4  Version 4

4.2.5  Version 5

4.2.6  Version graphique optionnelle




File translated from TEX by TTH, version 3.74.
On 14 Mar 2012, 20:39.