mardi 5 mars 2019

JList (3) : utilisation d'un écouteur (Listener) sur le modèle

Après la présentation d'un premier exemple simple (ici) qui montre la séparation entre la Vue et le Modèle dans les composants Swing et d'un deuxième exemple (ici) qui montre l'utilisation d'un Listener "logique" qui récupère les actions de l'utilisateur, cet article vise à montrer l'utilisation d'un Listener sur le modèle, c'est-à-dire, détecter qu'un changement a eu lieu dans le modèle de donnée.

Malgré qu'un tel écouteur peut être utilisé pour détecter des changements effectués par l'utilisateur, le plus intéressant est de l'utiliser pour détecter des changements appliqués par d'autres programmes ou bien d'autres threads.

Ainsi, pour cet article, deux classes seront nécessaires :
  • La fenêtre qui contiendra la liste et son modèle. Pour simplifier l'exemple, le modèle sera exposé via un simple getter.
  • Un "autre programme" qui simule une source externe du changement effectué sur le modèle de la liste.
L'écouteur sur un modèle de données ne cherche pas à détecter des actions de l'utilisateur. Mais, il se concentre sur les changements possibles des données. Ainsi, l'écouteur (Listener) ListDataListener propose trois méthodes :
  • intervalAdded
  • intervalRemoved
  • contentsChanged
Les deux premières permet de récupérer les événements simples, le troisième sert à récupérer des changements du contenu du modèle.


Les trois méthodes reçoivent le même objet événement : ListDataEvent


Si ce dernier ne cache pas les données changées, il garde les positions (début/fin) des intervalles affectées par le changement. Par la suite, il est possible de récupérer les données à partir du modèle lui-même.

Pour pouvoir utiliser directement ces fonctionnalités, il faut faire appel au moins à la classe AbstractListModel, d'ailleurs, c'est la valeur ajoutée principale de cette classe par rapport à l'interface de base ListModel. Autrement, tous les mécanismes internes doivent être implémentées (chose qui n'est pas vraiment difficile après tout).


Revenons à notre exemple. Il se compose de trois classes :
  • Une classe qui simule un programme externe qui change les données. Elle ajoute une donnée à partir d'une position aléatoire d'un tableau qui contient "quelques données".
  • Une fenêtre qui continent la liste et qui expose le modèle de la liste. Cette classe constitue aussi l'écouteur ListDtaListener. en recevant une nouvelle valeur, le texte d'une JLabel est mis à jour.
  • La classe qui contient le main crée une instance de chaque classe et les passe à deux thread séparés. Pour une meilleure visibilité, l'ajout des valeurs aléatoires s'effectue à des intervalles de 2 seconds. 
Ainsi, le code essentiel de la première classe :

class MonDeuxiemeProgramme {
 
 MaFrame frameAttachee;
 String[] quelquesDonnees = ...;

 public MonDeuxiemeProgramme(MaFrame frame){
  frameAttachee = frame;
 }
 
 public void ajouterElementAleatoire(){
  Random r = new Random();
  int valeur = r.nextInt(26);
  
  frameAttachee.getModele().addElement(quelquesDonnees[valeur]);
 }
 
}

Le code essentiel de la deuxième classe :


class MaFrame extends JFrame implements ListDataListener {

 JList liste;
 DefaultListModel modele;
 
 ...
 
 public MaFrame(){
  
  setTitle("Exemple JList");
  setSize(800, 400);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
  modele = new DefaultListModel();
  modele.addListDataListener(this);
  liste = new JList(modele);
  
  creerInterface();
  
 }
 
 public void creerInterface(){
  ...
 }
 
 public void intervalAdded(ListDataEvent e){
  lblMessage.setText("Ajout à la position " + e.getIndex0() + " (" + modele.get(e.getIndex0()) + ")");
 }
 
 public DefaultListModel getModele(){
  return modele;
 }
 
 public void intervalRemoved(ListDataEvent e){}
 
 public void contentsChanged(ListDataEvent e){}

} 

Le code complet :


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.event.*;
import java.util.*;

public class ExempleEvenementModelJList {
 
 public static void main (String args[]) {
  
  MaFrame frame = new MaFrame();
  MonDeuxiemeProgramme autre = new MonDeuxiemeProgramme(frame);
  
  Thread t1 = new Thread(new Runnable(){
   
   public void run(){
    frame.setVisible(true);
   }
   
  });
  
  Thread t2 = new Thread(new Runnable(){
   
   public void run(){
    while(true){
     try{
      Thread.sleep(2000);
      autre.ajouterElementAleatoire();
     }catch(Exception e){}
    }
   }
   
  });
  
  t1.start();
  t2.start();
  
 }
}

class MaFrame extends JFrame implements ListDataListener {

 JList liste;
 JScrollPane scroll;
 DefaultListModel modele;
 
 JLabel lblMessage;
 
 JPanel pnlDroite;
 JPanel pnlGauche;
 
 public MaFrame(){
  
  setTitle("Exemple JList");
  setSize(800, 400);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
  modele = new DefaultListModel();
  modele.addListDataListener(this);
  liste = new JList(modele);
  
  creerInterface();
  
 }
 
 public void creerInterface(){
  
  lblMessage = new JLabel("Pas d'élément pour le moment");
  lblMessage.setBounds(20, 20, 450, 30);
  
  pnlDroite = new JPanel();
  pnlDroite.setLayout(null);
  pnlDroite.add(lblMessage);
  pnlDroite.setPreferredSize(new Dimension(480, 360));
  
  scroll = new JScrollPane(liste);
  scroll.setBounds(0, 0, 250, 360);
  
  pnlGauche = new JPanel();
  pnlGauche.setLayout(null);
  pnlGauche.add(scroll);
  pnlGauche.setPreferredSize(new Dimension(280, 360));
  
  getContentPane().setLayout(new FlowLayout());
  getContentPane().add(pnlGauche);
  getContentPane().add(pnlDroite);
  
 }
 
 public void intervalAdded(ListDataEvent e){
  lblMessage.setText("Ajout à la position " + e.getIndex0() + " (" + modele.get(e.getIndex0()) + ")");
 }
 
 public DefaultListModel getModele(){
  return modele;
 }
 
 public void intervalRemoved(ListDataEvent e){}
 
 public void contentsChanged(ListDataEvent e){}

} 

class MonDeuxiemeProgramme {
 
 MaFrame frameAttachee;
 String[] quelquesDonnees = new String[]{"Alfa",
  "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf",
  "Hotel", "India", "Juliett", "Kilo", "Lima", "Mike",
  "November", "Oscar", "Papa", "Quebec", "Romeo", "Sierra",
  "Tango", "Uniform", "Victor", "Whiskey", "X-ray", "Yankee",
  "Zulu"};
 
 public MonDeuxiemeProgramme(MaFrame frame){
  frameAttachee = frame;
 }
 
 public void ajouterElementAleatoire(){
  Random r = new Random();
  int valeur = r.nextInt(26);
  
  frameAttachee.getModele().addElement(quelquesDonnees[valeur]);
 }
 
}

Résultat après quelques seconds :












lundi 4 mars 2019

JList (2) : Exemple avec écouteur (Listener) sur la liste elle-même

Ce code montre l'utilisation d'un écouteur (Listener) sur la liste elle-même pour détecter et gérer l'interaction entre cette dernière et l'utilisateur.

Ce code est le deuxième dans une série d'articles qui montrent l'utilité u modèle MVC respecté par les composants Swing et qui devient nécessaire pour les composants qui affichent plusieurs données.

Un premier exemple (avec une explication détaillée sur la création d'une JList avec un DefaultListModel) se trouve ici.

Dans ce deuxième code, la liste est associée à un écouteur pour surveiller les actions de sélection et de désélection des éléments de la liste.

Trois mode de sélection peuvent être définis pour une liste. La méthode setSelectionMode() prend un entier qui détermine le mode. Pour simplifier l'utilisation, les trois valeurs sont déclarées comme des constantes dans la classe ListSelectionModel avec des noms assez parlants. Elles sont :

  • ListSelectionModel.SINGLE_SELECTION 
  • ListSelectionModel.SINGLE_INTERVAL_SELECTION
  • ListSelectionModel.MULTIPLE_INTERVAL_SELECTION

Dans cet exemple, deux modes seront démontrés.

Pour pouvoir récupérer les changements dans la sélection, il suffit d'ajouter un ListSelectionListener. Ce dernier définit une seule méthode : public void valueChanged(ListSelectionEvent e). Malgré que l’événement ListSelectionEvent permet de récupérer toutes les informations utiles sur le changement dans la sélection, il est possible de faire appel à des méthodes dans la classe JList directement.


Néanmoins, les méthodes à appeler dépendent du modèle de sélection utilisé. En effet, si le mode de sélection est "SINGLE_SELECTION" alors il n'est pas pratique de faire appel aux méthodes qui récupèrent "la liste des éléments sélectionnés".

Pour basculer entre les deux modes de sélection démontrer, deux JRadioButton sont utilisés. Les deux sont associés à un écouteur (ChangeListener) pour surveiller le changement de la sélection et ainsi changer le mode de sélection de la liste.


Ainsi la partie la plus importante du code est :


 public void valueChanged(ListSelectionEvent e){
  if(uniqueSelection){
   
   int indice = liste.getSelectedIndex();
   
   if(indice != -1){
    String valeur = (String)liste.getSelectedValue();
    lblSelection.setText(valeur + "(" + indice + ")");
   }
   
  }else{
   
   int[] indices = liste.getSelectedIndices();
   List<String> valeurs = liste.getSelectedValuesList();
   
   String message = "";
   for(int i = 0; i < valeurs.size(); i++){ 
    message += valeurs.get(i) + "(" + indices[i] + ") ";
   }
   lblSelection.setText(message);
   
  }
 }

Le code complet :

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
import java.util.List;

public class ExempleSelectionJList 
  extends JFrame 
   implements ChangeListener, ListSelectionListener{
 
 JList liste;
 DefaultListModel<String> modele;
 
 String[] quelquesDonnees = new String[]{"Alfa",
  "Bravo", "Charlie", "Delta", "Echo", "Foxtrot", "Golf",
  "Hotel", "India", "Juliett", "Kilo", "Lima", "Mike",
  "November", "Oscar", "Papa", "Quebec", "Romeo", "Sierra",
  "Tango", "Uniform", "Victor", "Whiskey", "X-ray", "Yankee",
  "Zulu"};
 
 JRadioButton rdoUnique, rdoMultiple;
 ButtonGroup groupe;
 boolean uniqueSelection;
 
 JLabel lblSelection;
 JPanel pnlAjouter;
 
 public ExempleSelectionJList(){
  
  setTitle("Exemple Simple JList");
  setSize(800, 400);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
  modele = new DefaultListModel();
  liste = new JList(modele);
  liste.addListSelectionListener(this);
  
  creerFormulaire();
  remplirListe();
  
  getContentPane().add(pnlAjouter, BorderLayout.CENTER);
  getContentPane().add(new JScrollPane(liste), BorderLayout.WEST);
  
 }
 
 public void creerFormulaire(){
  
  rdoUnique = new JRadioButton("Choix Unique");
  rdoUnique.setBounds(20, 20, 150, 30);
  rdoMultiple = new JRadioButton("Choix Multiple");
  rdoMultiple.setBounds(190, 20, 150, 30);
  
  rdoUnique.addChangeListener(this);
  rdoMultiple.addChangeListener(this);
  
  groupe = new ButtonGroup();
  groupe.add(rdoUnique);
  groupe.add(rdoMultiple);
  
  rdoUnique.setSelected(true);
  uniqueSelection = true;
  
  lblSelection = new JLabel("La sélection s'affiche ici");
  lblSelection.setBounds(20, 70, 450, 30);
  
  
  pnlAjouter = new JPanel();
  pnlAjouter.setLayout(null);
  pnlAjouter.add(rdoUnique);
  pnlAjouter.add(rdoMultiple);
  pnlAjouter.add(lblSelection);
  
 }
 
 public void remplirListe(){
  for(int i = 0; i < quelquesDonnees.length; i++)
   modele.addElement(quelquesDonnees[i]);
 }
 
 public void valueChanged(ListSelectionEvent e){
  if(uniqueSelection){
   
   int indice = liste.getSelectedIndex();
   
   if(indice != -1){
    String valeur = (String)liste.getSelectedValue();
    lblSelection.setText(valeur + "(" + indice + ")");
   }
   
  }else{
   
   int[] indices = liste.getSelectedIndices();
   List<String> valeurs = liste.getSelectedValuesList();
   
   String message = "";
   for(int i = 0; i < valeurs.size(); i++){ 
    message += valeurs.get(i) + "(" + indices[i] + ") ";
   }
   lblSelection.setText(message);
   
  }
 }
 
 public void stateChanged(ChangeEvent e){
  uniqueSelection = rdoUnique.isSelected();
  if(uniqueSelection)
   liste.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
  else
   liste.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
 }
 
 public static void main (String args[]) {
  
  (new ExempleSelectionJList()).setVisible(true);
 }
}

Quelques résultats :






JList (1) : un premier exemple simple

Ce code présente un exemple très simple pour créer et ajouter des éléments à une JList.

Ce code a été créé comme un premier code dans une (petite) série pour mettre l'accent sur l'utilisation des modèles tels que définis par  l'approche MVC, cette dernière qui est respectée par les composants Swing en comparaison avec les composants AWT.

Si la manipulation du modèle (donnée) associé à un composant simple comme JTextField, ce n'est pas de même pour les composants qui affichent plusieurs données tels que JComboBox, JList et JTable.

Dans cette série, JList sera choisie pour démontrer quelques fonctionnalités.

Dans cet premier code, une JList est créé en se basant sur DefaultListModel. En effet, les différents modèles sont disponibles comme des interfaces.


Pour simplifier leur utilisation (garantir les fonctionnalités de base communes), une classe abstraite qui implémente le minimum des fonctionnalités est livrée. Cela est valide pour tous les modèles des données pour les autres composants. Pour le cas de la JList, la classe abstraite est AbstractListModel :


Néanmoins, l'interface et la classe abstraite ne donnent aucune implémentation réelle qui supportent la sauvegarde des données et qui est prête pour être utilisée. C'est pourquoi, une implémentation par défaut est livrée. Cela aussi est valide pour les autres modèles des données des autres composants Swing. Pour la JList, la classe par défaut est DefaultListModel (c'est très explicit comme noms de classes) :


Cette dernière utilise un Vector pour stocker les données :

private Vector delegate = new Vector();


Le code suivant, montre comment créer une JList avec un DefaultListModel. Le code de création des autres composants graphiques est séparé. Le bouton permet d'ajouter la valeur saisie dans le champs à la liste (à gauche) :

Code source :


import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class ExempleSimpleJList extends JFrame implements ActionListener {
 
 JList liste;
 DefaultListModel modele;
 
 JLabel lblNouveau;
 JTextField txtNouveau;
 JButton btnAjouter;
 JPanel pnlAjouter;
 
 public ExempleSimpleJList(){
  
  setTitle("Exemple Simple JList");
  setSize(800, 400);
  setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  
  modele = new DefaultListModel();
  liste = new JList(modele);
  
  creerFormulaire();
  
  getContentPane().add(pnlAjouter, BorderLayout.CENTER);
  getContentPane().add(new JScrollPane(liste), BorderLayout.WEST);
  
 }
 
 public void actionPerformed(ActionEvent e){
  modele.addElement(txtNouveau.getText());
 }
 
 public void creerFormulaire(){
  
  lblNouveau = new JLabel("Nouveau Element :");
  lblNouveau.setBounds(20, 20, 150, 30);
  txtNouveau = new JTextField();
  txtNouveau.setBounds(190, 20, 150, 30);
  btnAjouter = new JButton("Ajouter");
  btnAjouter.setBounds(20, 70, 150, 30);
  btnAjouter.addActionListener(this);
  
  pnlAjouter = new JPanel();
  pnlAjouter.setLayout(null);
  pnlAjouter.add(lblNouveau);
  pnlAjouter.add(txtNouveau);
  pnlAjouter.add(btnAjouter);
  
 }
 
 public static void main (String args[]) {
  
  (new ExempleSimpleJList()).setVisible(true);
 }
}

Résultat :


lundi 24 septembre 2018

Pratique sur les boucles : Afficher les multiples d'un nombre

Énoncé 

Ecrire un algorithme qui affiche le nombre des entiers qui sont des multiples de 3 et inférieur à un nombre n donné par l'utilisateur.

Solution(s)

Plusieurs solutions peuvent être données. Il s'agit d'un autre exercice très classique pour commencer avec les boucles.
Premièrement, nous pouvons voir qu'il y a une borne supérieure à ne pas dépasser. Cela veut dire que le nombre d'itérations est connu et la boucle "Pour" peut être utilisée (toute boucle peut être écrite sous la forme Tant Que).
Ainsi, la solution la plus simple et la plus intuitive sera composée de :
  • Une boucle qui parcours les valeurs jusqu'à n,
  • Une structure conditionnelle pour vérifier est ce qu'il s'agit d'un multiple de 3 pour l'afficher.
En Pascal :
Program AfficherMultiples3;

Var 
 n, i : Integer;

Begin
 
 WriteLn('Faites entrer la limite n :');
 ReadLn(n);
 
 For i := 0 to n Do
  If (i mod 3 = 0) Then
  WriteLn(i, ' est un multiple de 3');
  
 ReadLn;
 
 
End.

En Java :
import java.util.Scanner;

public class AfficherMultiples3 {
 
 public static void main (String args[]) {
  
  System.out.println("(Java) Faites entrer la limite n :");
  
  Scanner entree = new Scanner(System.in);
  int n = entree.nextInt();
  
  for(int i = 0; i <= n; i++)
   if(i % 3 == 0)
    System.out.println(i + " est un multiple de 3");
  
 }
 
}

Le résultat d'exécution est exactement le même pour les deux codes :


D'habitude, l'étape suivante est de montrer que même avec ce petit code, on arrive à l'optimiser. En effet, pourquoi parcourir toutes les valeurs et faire le test pour chaque valeur. Il est possible de ne parcourir que les valeurs désirées, c'est à dire, il est possible de parcourir les multiples de 3 seulement. L'idée réside dans le pas effectué par la boucle Pour à chaque itération.

En Pascal (j'utilise fpc qui ne supporte pas des pas dans la boucles For, alors je suis obligé de passer à la boucle While):

Program AfficherMultiples3;

Var 
 n, i : Integer;

Begin
 
 WriteLn('Faites entrer la limite n :');
 ReadLn(n);
 
 i := 0;
 While(i <= n)Do
 Begin
  WriteLn(i, ' est un multiple de 3');
  i := i + 3; { Le compteur change par 3 à chaque fois }
 End;
  
 ReadLn;
 
 
End.

En Java :

import java.util.Scanner;

public class AfficherMultiples3 {
 
 public static void main (String args[]) {
  
  System.out.println("(Java) Faites entrer la limite n :");
  
  Scanner entree = new Scanner(System.in);
  int n = entree.nextInt();
  
  for(int i = 0; i <= n; i+=3 /* le pas est 3 */)
   System.out.println(i + " est un multiple de 3");
  
 }
 
}

Ces deux codes donnent exactement les mêmes résultats mais dans un temps d'exécution plus court.




mardi 8 mai 2018

BigDecimal : pour les calculs avec une grande précision

La précision du calcul avec les nombres en virgule flottante dépend fortement de la taille (nombre de bits) de ces nombres.
Ainsi, il est très facile de montrer les limites des différents types élémentaires largement utilisés. Par exemple, le code suivant qui utilise le type float :

public class ExempleBigDecimal {
 
 public static void main (String args[]) {
  
  float exemple = (float)34/145;
  System.out.println(exemple);
  
 }
}

Affiche le résultat suivant :


Pour augmenter la précision, il est possible d'utiliser le type double. Le code suivant :

public class ExempleBigDecimal {
 
 public static void main (String args[]) {
  
  double exemple = (double)34/145;
  System.out.println(exemple);
  
 }
}

Donne le résultat suivant :


Les deux résultats sont loin d'être complets et précis. Pour atteindre une précision beaucoup plus supérieure, nous pouvons utiliser les BigDecimal. BigDecimal est une classe du package java.math. Elle permet de créer des nombres avec des grandes précisions et de faire des opérations arithmétiques sur ces nombres. Comme étant une classe, les opérateurs traditionnels (+, -, *, /, %) ne peuvent pas être appliqués directement. Il faut faire recours à des fonctions pour effectuer ces opérations.
Le code suivant fait le même calcul que les deux codes cités ci-dessus. La précision choisie est 20 chiffres après la virgule :

import java.math.BigDecimal;
import java.math.RoundingMode;

public class ExempleBigDecimal {
 
 public static void main (String args[]) {
  
  BigDecimal bd34 = new BigDecimal(34);
  BigDecimal bd145 = new BigDecimal(145);
  BigDecimal result = bd34.divide(bd145, 20, RoundingMode.DOWN);
  System.out.println(result.toPlainString());
  
 }
}

Il affiche le résultat suivant :


Mettons les trois codes ensemble et augmontons la précision à 100 chiffres après la virgule :

import java.math.BigDecimal;
import java.math.RoundingMode;

public class ExempleBigDecimal {
 
 public static void main (String args[]) {
  
  float exemplef = (float)34/145;
  System.out.println("Float      : " + exemplef);
  
  double exempled = (double)34/145;
  System.out.println("Double     : " + exempled);
  
  BigDecimal bd34 = new BigDecimal(34);
  BigDecimal bd145 = new BigDecimal(145);
  BigDecimal result = bd34.divide(bd145, 100, RoundingMode.DOWN);
  System.out.println("BigDecimal : " +result.toPlainString());
  
 }
}

Le résultat sera :


Il est important de noter que ces opérations sont beaucoup plus lentes. Un test rapide :


import java.math.BigDecimal;
import java.math.RoundingMode;

public class ExempleBigDecimal {
 
 public static void main (String args[]) {
  
  float exemplef;
  long d = System.currentTimeMillis();
  for(int i = 0; i < 1000; i++)
   exemplef = (float)34/145;
  long f = System.currentTimeMillis(); 
  System.out.println("Float temps 1000 opérations    : " + (f - d));
  
  double exempled;
  d = System.currentTimeMillis();
  for(int i = 0; i < 1000; i++)
   exempled = (double)34/145;
  f = System.currentTimeMillis(); 
  System.out.println("Double temps 1000 opérations    : " + (f - d));
  
  BigDecimal bd34 = new BigDecimal(34);
  BigDecimal bd145 = new BigDecimal(145);
  BigDecimal result;
  d = System.currentTimeMillis();
  for(int i = 0; i < 1000; i++)
   result = bd34.divide(bd145, 100, RoundingMode.DOWN);
  f = System.currentTimeMillis(); 
  System.out.println("BigDecimal temps 1000 opérations : " + (f - d));
  
 }
}

Le résultat est :

Nous voyons clairement que 1000 opérations de division en BigDecimal sont beaucoup plus lentes que les opérateurs traditionnels.

lundi 2 avril 2018

Les fonctions : par analogie avec les fonctions mathématiques

Les fonctions sont présentes dans tous les programmes. Il est pratiquement impossible d'écrire un programme qui effectue plusieurs tâches sans faire recours aux fonctions (pas impossible mais très difficile, pénible et coûteux).

Dans cet article, je vais essayer de présenter la notion de fonction en la rapprochant de la notion de fonction mathématique; une notion largement plus maîtrisée.

Une fonction mathématique à une seule variable peut être déclarée par la forme suivant :


Cette déclaration se divise en deux partie :
  • La première partie désigne l'ensemble de départ; l'ensemble dans lequel la variable d'entrée va prendre ses valeurs.
  • La deuxième partie désigne l'ensemble d'arrivé; l'ensemble dans lequel la fonction prend ses valeurs.

Un exemple concret :



Ainsi, cette fonction prend une variable réelle et renvoie une valeur réelle. Cette valeur est calculée comme étant le double du cub de la valeur prise en entrée.

Plus généralement, une fonction à n variables est déclarées de la manière suivante :


La première partie désigne un produit cartésien de plusieurs ensemble, c'est à dire, la fonction prend un t-uple en entrée et prend ses valeur dans un ensemble d'arrivé.

Un exemple concret :

Cette fonction prend un couple de nombres réels et prend ses valeurs dans l'ensemble des nombres réels. La deuxième partie montre la formule de calcule.

La deuxième partie peut être un peu plus compliqué qu'une formule unique. La fonction "valeur absolue", par exemple, est définie comme suit :

Ainsi, la formule varie selon la valeur de la variable.

Passons maintenant à la programmation.

La déclaration d'une fonction doit préserver, au moins, les notions requises par la déclaration mathématique. Autrement, la conception d'une fonction sera vraiment difficile à imaginer.

Ainsi, il faut garder :
  • Les ensemble de départ et l'ensemble d'arrivé.
  • La formule du calcul.

En Pascal, la déclaration sera ainsi :

function f([parametres : ensembles de depart]) : [ensemble d'arrivée];

reprenons l'exemple d'une fonction à une seule variable :

function f(x : Real) : Real;

La deuxième partie est facilement réalisable grace aux structures de contrôle offertes par le langage (le conditionnel et les boucles). Ainsi le code de la première fonction sera :

Function f(x : Real) : Real;
Begin
 f := 2 * x * x * x;
End;

Et la fonction qui implémente la fonction "valeur absolue" sera :

Function valeurAbsolue(n : Integer) : Integer;
Begin
 If(n >= 0)Then
  valeurAbsolue := n
 Else
  valeurAbsolue := -1 * n;
End;

Pour appeler une fonction, c'est comme appeler une personne :), c'est par son nom sans oublier de lui fournir les valeurs nécessaires en entrée (les paramètres). Un exemple complet :


Program ExempleFonctions;

Function f1(x : Real) : Real;
Begin
 f1 := 2 * x * x * x;
End;

Function f2(x, y : Real) : Real;
Begin
 f2 := x * x + y * y;
End;

Function valeurAbsolue(n : Integer) : Integer;
Begin
 If(n >= 0)Then
  valeurAbsolue := n
 Else
  valeurAbsolue := -1 * n;
End;

Begin
 
 WriteLn(f1(3.14):4:2);
 WriteLn(f2(2.5, 3.5):4:2);
 WriteLn(valeurAbsolue(-10));
 
End.