import static java.lang.System.*;   // cf. Java 5
import static java.lang.Math.*;

import java.io.*;
import javax.swing.*;

/**
  * 'fact_r1' : Calcul récursif de factorielle avec mesure de durée
  *            d'exécution via une amplification adéquate avec 'nanoTime' ...
  *  @author  (c)~/2a env. H. Nguyen-Phu
  *  @version 1.3  2006.11.04  (Java 5.0 or more)
  *  @since   1.0  2002.11.25
  */
public class fact_r1 extends MesureDeDuree1 {

   /**
     * jo: champ public de classe <===> alias de 'System.jo' pour JDK 1.4 ou antérieure ...
     *       Il n'a plus de raison d'être avec  "import static java.lang.System.*;"
     *       car il est remplacé directement  par 'jo'  sous JDK 5.0
     */
  static PrintWriter jo = new PrintWriter(System.out, true);

  public static int n;

   /**
     * Déclaration et définition récursive de la méthode de classe 'FACT(N)'
     * @param N  un entier naturel
     * @return   un entier long = N!
     */
  public static long FACT(int N)  {
    if (N<= 1) return 1;
    return	N*FACT(N-1);
  }

   /**
     * Définition de la méthode d'instance  'TraitementAMesurer'
     * Sa déclaration a été donnée dans la super classe 'MesureDeDuree'
     * @return un entier long = n!
     */
  long TraitementAMesurer()  {  // Calcul de n!
       return FACT(n);
  }

  public static void main(String args[]) throws IOException  {

    jo.println("fact_r1.java: Calcul du factoriel N par r\u00e9cursion (0<= N <=20)");
    jo.println("------- Usage:  java  fact_r1   unEntier \n");
    jo.println("Par d\u00e9faut N= 20. Emploi de 'nanoTime()' (c)~/2A env. 2006.11.04 10h47\n");

    jo.println("Exercice: Faire la r\u00e9tro-analyse du prog. et d\u00e9duire le principe algorithmique");
    jo.println("--------  de mesure des dur\u00e9es de calcul inf\u00e9rieures a` 0,050 seconde.\n");

    if (args.length == 0)	n = 20;
      else { 	n = Integer.parseInt(args[0]);
		if (n < 0 || n > 20)  n = 20;
    }

    Kmax= 1000000; // facteur d'amplification pq  Duree totale >> 50 ms.
//  Kmax: 1er champ protégé dans la super classe: 'MesureDeDuree'

    fact_r1  monTest = new fact_r1();

    String resultat = "Factorielle:  "+ n +"! = "+res+" / 'long'\n";
//  res: 2nd champ protégé dans la super classe: 'MesureDeDuree1'
    long startTime = System.nanoTime();
         res= FACT(20);
    long estimatedTime = System.nanoTime() - startTime;
    jo.printf("Sans amplification,  Duree estime'e /'nanoTime()' =  %9.2e  s !\n\n", ((double)estimatedTime * 1e-09) );

    jo.println(resultat);
    if (n > 0)  {
      double factN = pow(n/E, n)*sqrt(2d*PI*n)*(1d+1.002/12d/n);
      jo.println("Stirling approx. # "+factN);  // pour vérification
    }
// Affichage dans la boîte de dialogue du résultat final: n!
    JOptionPane.showMessageDialog(null,resultat);
    es.attente();       // Pour stabiliser l'écran pour lecture ...
    System.exit(0);
  }
}

