mardi 18 mars 2014

Programmation - const vs static readonly

J'ai vu récemment plusieur commentaire sur Internet proposant des utilisation pour les const et le static readonly. J'ai eu l'impression qu'il y avait un manque de compréhension à ce niveau. La différence entre les 2 est pourtant fort simple. Lorsque possible, il faut utiliser le const autant que possible, car il sera optimisé par le compilateur.

public const String MaConstante = "ValeurDeMaConstante";

Pour sa part, les static readonly doit être utilisé dans le cas où la constante nécessite l'appel d'un constructeur par exemple, car le compilateur ne peut pas faire ces appels.



public static readonly Foo MaConstante = new Foo(){ Propriete1 = -1, Propriete2 = "Valeur" };

Il est donc possible d'utiliser les variables static readonly pour définir des objets avec des valeurs par défaut et connues, comme String.Empty et Guid.Empty, en utilisant le contructeur de la classe, et ainsi s'épargner quelques mots de tête.

mercredi 14 juillet 2010

Programmation - Cours 1 - Les variables et les objets

En programmation, il y a principalement 3 choses à savoir, les variables, les fonctions, et les classes.
Les variables servent à stocker des informations, que ce soit un nombre, un texte ou tout autres informations, pouvant être gérée par des classes qui seront expliquées plus tard.
Les variables sont définis de différentes façons. Dans les exemples suivant, on défini des entiers.

  • C#
  • C++
  • VB

int i = 2;
var j = 3;

La méthode de programmation la plus utilisée actuellement est l'orienté objet. Ce qui représente les objets, ce sont les variables. Les classe sont les définitions de ces objets. En regroupant les types de base, avec des variables, on crée des classe qui sont plus complexe. On peut ainsi utiliser ces classe pour déclarer de nouvelles variables.

jeudi 8 juillet 2010

Programmation 1 - Optimisation - Fibonacci, Calcul Récursif ou Itératif ?

Ces derniers temps, j'ai recommencé à faire la lecture de plus en plus de code. Certains étaient bien écrit, d'autre moins. J'ai donc décidé de faire ma part et de démontrer ce que j'y ai vu de bien, et de moins bien.

L'un des exemples que j'ai vu, était le calcul de la suite de Fibonacci. Une bonne chose avec le calcul de la suite de Fibonacci, c'est que l'on peut y appliquer les modèles de calcul récursif ou itératif.

Qu'est-ce que la suite de Fibonacci?

La suite de Fibonacci est une suite mathématiques qui, à l'origine, devait répondre à la question:
Un homme met un couple de lapins dans un lieu isolé de tous les côtés par un mur. Combien de couples obtient-on en un an si chaque couple engendre tous les mois un nouveau couple à compter du troisième mois de son existence?
Source: Wikipedia

En résumé, chaque nombre, est la somme des 2 nombres précédent, en utilisant 0 et 1 comme point de départ, ce qui nous donne la suite: 0, 1, 1, 2, 3, 5, 8, 13, 21, ...


Le Calcul Récursif
Le calcul récursif, qui était la méthode de choix de plusieurs de mes professeurs à l'Université, quoique plus compréhensible, est très loin d'être le meilleur choix au niveau des performances.

Le calcul récursif implique d'écrire une fonction qui s'appelle elle même.

  • C#
public static ulong Fibonacci_Recursive(uint n)
{
    if (2 > n)
        return n;

    return Fibonacci_Recursive(n - 1) + Fibonacci_Recursive(n - 2);
}

Le développement de ce calcul, nous montre que la valeur n-2 sera calculé 2 fois, n-3 sera calcul 3 fois, et ainsi de suite.

De ce fait, il est évident qu'il doit y avoir une méthode plus optimisée qui ne fera pas le même calcul plus d'une fois. L'utilisation d'une cache, pour stocker les valeurs déjà calculées, serait un avantage, mais il faudra vérifier si le résultat est déjà stocké. Calculer une valeur très grande demandera plus de temps au départ, mais apportera une grande amélioration comparativement au cas de base. Il faut par contre considérer l'utilisation de la mémoire. Ce n'est pas un problème dans bien des cas, mais il peut arriver qu'une application soit plus rapide si elle n'utilise que la cache du processeur, sans même passer par la mémoire vive. Ce type d'optimisation est plus rare, et est nécessaire seulement dans des cas extrêmes, mais il est bien de le savoir. Il faut aussi prendre en compte que les appels subséquents seront plus rapide, car le résultat est déjà calculé. Tout dépend du nombre d'appel que nous prévoyons pour cette fonction.

  • C#
static List<ulong> fib = new List<ulong>();
public static ulong Fibonacci_Recursive_buffer(uint n)
{
    if (fib.Count > n)
        return fib[(int)n];

    if (2 > n)
    {
        for(ulong i = (ulong)fib.Count; i <= n; ++i)
            fib.Add(i);
    }
    else
    {
        fib.Add(Fibonacci_Recursive_buffer(n - 1) + Fibonacci_Recursive_buffer(n - 2));
    }

    return fib[(int)n];
}

De plus, dans un cas récursif, la pile, qui accumule les appels de fonctions, peut poser un problème dans le cas de très grande valeur. Ce ne sera pas le cas ici, car le résultat ne sera pas bon pour une valeur supérieure à 83.

Le Calcul Itératif
Le calcul itératif est une boucle qui s'exécute plusieurs fois.Donc, plutôt que de s'appeler elle-même est exécute un nombre de ligne de code un certain nombre de fois. Je privilégie cette méthode dans plusieurs cas, elle n'est par contre pas toujours la meilleure solution.

J'ai trouvé sur Internet le code suivant.

  • C#
public static ulong Fibonacci_Iterative(ulong n)
{
    ulong t = 0, i = 0, v = 0, w;

    do
    {
        w = v;
        v = t;
        t = i < 2 ? i : t + w;
    } while (i++ < n);

    return t;
}

L'auteur disait bien sûr qu'il n'y avait pas moyen de faire plus rapide. Il y a par contre, 2 problèmes dans son code. Le premier problème, c'est que pour le cas $n = 0$, la boucle do{...}while() se fait une fois, même si cela n'est pas nécessaire. Le deuxième problème est plus important, car il touche directement les performances. À l'intérieur de sa boucle, il y a une condition (t = i < 2 ? i : t + w;) qui ralentit le code et qui n'est pas nécessaire pour $i \geq 2$. Il est facile d'éviter ce cas en initialisant correctement t, v et w. La version corrigé est ainsi environ 20% plus rapide.

  • C#
public static ulong Fibonacci_Iterative_Faster(ulong n)
{
    ulong result = 0, f1 = 1, f2, i = 1;

    while (i <= n)
    {
        f2 = f1;
        f1 = result;
        result = result + f2;
        ++i;
    }

    return result;
}

L'utilisation ici d'une cache pour stocker les résultats peut aussi être considéré, mais à ce moment, il n'y a pas vraiment d'avantage à utiliser la méthode itérative versus la méthode récursive, car si la cache accélère le premier calcul en récursion, elle le ralentit en itération. Il faut donc considérer le nombre d'appel qui sera fait pour prendre la bonne décision.

Performance et Temps d'exécution

J'ai programmé chacun de ces algorithmes afin de tester la performance dont voici les résultats:

Les temps affichés sont en millisecondes. Le code récursif a été fait avec $n = 40$, les 3 autres ont été exécuter 1000000 de fois avec $n = 80$. Le code récursif ayant une complexité exponentiel est un des problèmes. L'utilisation de la cache permet tout de même de comparer. De plus, pour ce test, j'ai effacé la cache avant chaque calcul de manière à pouvoir le comparer dans le cas d'un seul calcul. Lorsque nous conservons la cache, on obtient un temps inférieur aux calculs itératifs, mais il faut rappeler que la cache occupe de la mémoire qui peut être problématique dans certains cas.

mercredi 7 juillet 2010

Programmation - Cours 0 - La programmation

Passage obligé pour tout les cours: Qu'est-ce que la programmation?
La programmation, c'est un peu comme apprendre une nouvelle langue, avec la syntaxe et la structure de phrase. On utilise la programmation pour créer une simple application qui affiche un message à l'écran

Heureusement, de nos jours, programmer est beaucoup plus simple. Avec des logiciels comme Visual Studio, Netbeans, et autres qui crée maintenant les projets automatiquement et démarre avec un code fonctionnel. De plus, il y a maintenant plein d'exemple de code sur Internet qui peuvent servir de base. Si vous commencez, je vous suggère de commencer par des exemples de code simple.

Code

Le code par lequel tout le monde commence, un simple affichage de "Bonjour!!".
  • C#
  • C++
  • VB
static void Main()
{
    Console.WriteLine("Bonjour!!");
}

Le code est simple, ce qui est parfait pour commencer.


Capture d'écran

Voici ce que vous devriez obtenir.


Téléchargements

Présentation - Qui suis-je?

Je suis Pier-Luc Duchaine, j'ai un Baccalauréat en Génie Informatique de l'Université Laval, et je travaille en tant qu'Ingénieur et Programmeur analyste depuis maintenant 6 ans.

J'ai simplement un Baccalauréat, car j'ai privilégié l'expérience de travail, plutôt que de faire une maîtrise, et que de tout ceux que j'ai connu dans le domaine, pour ceux qui avait une maîtrise, n'avait pas acquis leur connaissances et leur savoir-faire durant leur maîtrise. Et que les employeurs que j'ai eu jusqu'à présent, n'ont pas donnés d'avantage au gens qui avait une maîtrise.

J'ai, par le passé, travaillé sur des systèmes embarqués à traitement en temps réel, ce qui paraîtra sûrement lors de certaines présentations que je ferai ici.

Je ferai donc ici des présentations pour apprendre à quelqu'un à programmer à partir de rien. Je fournirai des références, et des liens vers des sites intéressant. J'inscrirai donc ici principalement du code en C#, car il est plus simple pour la majorité, et a un format simple à comprendre. Et à ceux qui diront que ce n'est pas le meilleur langage, je leur répondrai qu'il y a une façon d'écrire exactement le même code dans tout les langages de programmation, et que les performances seront similaires. La seule différence, c'est que certains langages offre des fonctions qui n'existe pas ailleurs. Il est par contre possible de les écrire.