Une vraie calculatrice : écriture 2d : on marque la ligne entière de calcul, et le programme fait le reste !

Description

Vous en avez marre de ces sources de calculette qui se contentent de vous offrir des boutons ?
Je comprends.
Cependant, il faut avouer que la réalisation d'une calculatrice capable de transformer le string :
(sqr(e(ln((1+3)*(1/(2^2))))))^2
en calcul n'est pas facile (pour les plus courageux, ca vaut 1 :-))!
Il faut bien penser que les maths ne nous simplifient pas le travail : priorité des opérations, parenthèses (le code 2(2+1) = 2*(2+1) n'est pas forcément évident !)...

Cette calculette semble bien s'en tirer...cependant, j'ai commencé à la programmer il y a 48h, il est donc possible que certains bugs se soient dissimulés.

Vous trouverez l'ensemble du code source ainsi que d'autres captures d'écran sur http://neamar.fr/Res/Calc/

EDIT : A priori, j'ai corrigé tous les bugs auxquels je pouvais penser. La calculette fonctionne correctement pour l'ensemble des calculs que je lui ai fournis, mais cela ne veut pas dire qu'elle est bug-free !
Le code est extrêmement commenté...il n'utilise aucune API, aucune fonction avancée..le calcul est entièrement géré par le module appelé "Théorie". (211 lignes de code // 84 lignes de commentaires)

Le module "Graphique", quant à lui, "colorie" le code : il met en exposant les puissances, met le contenu des parenthèses en couleur...(utilisation du contrôle RichTextBox 6.0)(41 lignes de code // 8 lignes de commentaires)

Et la Form ne contient que 30 lignes...

La calculette gère les opérations standards : + - * / % (modulo), et ! (factorielle),ainsi que e (exponentielle), ln (logarithme népérien),tan et atn, avec gestion des priorités! C'est à dire que
1 + 2/2 = 2
...ce qui pour l'ordinateur n'était pas forcément évident !
Il y a aussi un outil somme, qui s'utilise de la façon suivante :
somme([Nom_Variable]=[départ],[Arrivee],[Calcul])
Cette somme est incorporable dans n'importe quel calcul, et vous pouvez même effectuer des sommes à l'intérieur de somme à l'intérieur de somme à l'intérieur de sommes...bref!
Par exemple, le code suivant renvoie une approximation de PI en utilisant la méthode du développement limité d'arctangente :
4*somme(k=0,5000,(-1)^k*(1/(2*k+1)))

Les calculs se font avec des variables Double...ce qui laisse assez de marges pour les calculs.

Je note la source comme initié, car elle fait appel à la notion de récursivité, pas forcément facile à comprendre.
Tutorial sur la récursivité : http://www.siteduzero.com/tuto-3-23774-1-la-recursivite.html

Source / Exemple :


'Le concept géneral :
Public Function Math_It(Expression As String) As Double
    'Cette fonction transforme un string passé en paramètre en nombre réel, c'est bien entendu la plus importante du programme !
    'On va effectuer une boucle : pour chaque caractère, on réflechira comment le traiter
    For i = 1 To Taille
        Caractere_Actuel = Mid$(Expression, i, 1)
        ...
                If Caractere_Actuel = "(" Then
                    'Voilà le cas intéressant du problème : si on a  des parenthèses...on fait appel à la récursivité.
                    'D'abord, il faut trouver la parenthèse correspondante, et l'envoyer à math_It (oui oui, la fonction dans laquelle on est !)
                    'ainsi, pour le calcul suivant : 2*(1+3) on va d'abord calculer (1+3) et ensuite * par 2
                    'Avant de faire ca cependant, il faut s'occuper du cas ou l'on a mis le nombre en facteur 2(1+3), car pour le programme, le * n'existe pas !
'                    If i <> 1 Then
'                        If IsNumeric(Mid$(Expression, i - 1, 1)) Then
'                            Somme = Calculer(Derniere_Operation, Somme, Nombre_Actuel)
'                            Derniere_Operation = "*"
'                        End If
'                    End If
                    Fin_Bloc_Instruction = TrouverParentheseFermante(Mid$(Expression, i + 1))
                    Nombre_Actuel = Math_It(Mid$(Expression, i + 1, Fin_Bloc_Instruction))
                    i = i + Fin_Bloc_Instruction
                End If
          .......
     Next
    'Ca y est, c'est terminé ! On effectue la dernière opération avec les derniers nombres, et on renvoie.
    Somme = Calculer(Derniere_Operation, Somme, Nombre_Actuel)

Conclusion :


Si vous ne comprenez pas tout, lancez un calcul, et regardez la fenêtre exécution : elle affiche en temps réel les calculs effectués.

Par exemple :

Initialisation du calcul (sqr(e(ln((1+3)*(1/(2^2))))))^2
-------------------------------------------------------
Math_It va effectuer le calcul (sqr(e(ln((1+3)*(1/(2^2))))))^2
Math_It va effectuer le calcul sqr(e(ln((1+3)*(1/(2^2)))))
Math_It va effectuer le calcul (e(ln((1+3)*(1/(2^2)))))
Math_It va effectuer le calcul (ln((1+3)*(1/(2^2))))
Math_It va effectuer le calcul ((1+3)*(1/(2^2)))
Math_It va effectuer le calcul 1+3
Math_It va effectuer le calcul 3
3 a renvoyé 3
1+3 a renvoyé 4
Math_It va effectuer le calcul 1/(2^2)
Math_It va effectuer le calcul 2^2
Math_It va effectuer le calcul 2
2 a renvoyé 2
2^2 a renvoyé 4
1/(2^2) a renvoyé 0,25
(1+3)*(1/(2^2)) a renvoyé 1
ln((1+3)*(1/(2^2))) a renvoyé 0
e(ln((1+3)*(1/(2^2)))) a renvoyé 1
sqr(e(ln((1+3)*(1/(2^2))))) a renvoyé 1
Math_It va effectuer le calcul 2
2 a renvoyé 2
(sqr(e(ln((1+3)*(1/(2^2))))))^2 a renvoyé 1

Comme vous le voyez, le calcul se décompose sous plusieurs formes très simples...(ce qui est, rappelons le, le but de la récursivité !)

De plus, le code est extrêmement souple : si quelqu'un voulait par exemple créer un grapheur, il n'y aurait pas de grosses difficultés.
De même, si quelqu'un souhaitait le passer dans un autre langage, il lui suffirait de traduire le module théorie dans le bon langage...Comme ce module utilise des fonctions communes à tous les langages, il n'y a aucun problème.

Quant à la rapidité, c'est acceptable : pour un DL (Développement Limité) de 5000 termes, le temps d'exécution est << 2 secondes.

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.