COMPILATEUR D'EXPRESSIONS MATHEMATIQUES

cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 - 5 janv. 2003 à 23:31
amiga68 Messages postés 54 Date d'inscription dimanche 23 février 2003 Statut Membre Dernière intervention 21 décembre 2009 - 6 avril 2013 à 12:22
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/12274-compilateur-d-expressions-mathematiques

amiga68 Messages postés 54 Date d'inscription dimanche 23 février 2003 Statut Membre Dernière intervention 21 décembre 2009
6 avril 2013 à 12:22
Ben ça fait longtemps ?

Je suis revenu voir cette excellente source

Proposition d'ajout : cube (³ Alt 0179)

Dans les constantes : ajout de MAX8CUBICROOT

const
MAX_FACT = 170;
MAX_SQR = 1e154;
//****************************************************************
MAX_CUBICROOT = 5.5396582567544642107741681454952e102;
//****************************************************************

Dans la partie implémentation, (function Expr1st: Double;)

Après le carré :

'³' : begin
if Result > MAX_CUBICROOT then
begin
Error := Idx;
Description := Err_OverFlow;
Exit;
end;
Result := Result * Result * Result ;
Next;
end;
cs_gege58 Messages postés 15 Date d'inscription vendredi 14 mai 2004 Statut Membre Dernière intervention 25 janvier 2009
15 mai 2005 à 19:45
Visiblement, il y a unanimité. Moi, je n'ai pas trouve le mode d'emploi, ni même une seule ligne de commentaire ??? !!!
Scalpweb Messages postés 1467 Date d'inscription samedi 13 mars 2004 Statut Membre Dernière intervention 5 mai 2010 4
1 août 2004 à 12:58
Exelente source !
cs_grandvizir Messages postés 1106 Date d'inscription samedi 8 novembre 2003 Statut Membre Dernière intervention 3 septembre 2006 22
7 mars 2004 à 18:53
Moi, j'ai regardé et c'est bien fait. Surtout le ^ montrant où est l'erreur La présentation m'a trop fait penser à Derive de Ti. De plus j'ai quelques idées:

> gérer le caractère "³" pour le cube.

> faire une variable REP ou ANS pour récupérer le dernier résultat, voir ANS(n) pour récupérer le nnième dernier résultat.

> la sélection qui met dans le presse-papier n'est pas évident. Le truc pas mal: Memo.onMouseUp:=<Edit.SelText:=Memo.SelText>. C'est copié direct dans l'edit sans passer par le presse-papier, parce que si j'ai déjà un truc dedans, je vais pas être content.

> pourquoi ne pas utiliser EXTENDED au lieu de DOUBLE. C'est bien plus grand.

> Pourquoi la virgule n'est pas supportée ?

> faire une formule (genre DEFINE x AS 3,45) définissant une variable X dans un TStringList et utilisable dans un calcul suivant, car l'interpréteur reconnaitra cette variable. Parce que si j'ai que l'exe, alors je peux pas toucher au source pour le faire.

> WordWrap=false pour le Memo

> améliorer la sortie. J'avais chargé l'exe, et détruit le répertoire juste après. Ce qui fait que l'exe ne se ferme plus à cause de <"Ne peut pas créer History.txt">. Remplacer par:
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
try
StrList.SaveToFile(HistoryFile);
except
end;
end;
jolijoli Messages postés 3 Date d'inscription mercredi 22 octobre 2003 Statut Membre Dernière intervention 20 décembre 2010
22 oct. 2003 à 19:16
Pour un premier contact
tout cela me parait très intéressant et bien fait.
Merci
cs_ZED Messages postés 57 Date d'inscription dimanche 14 avril 2002 Statut Membre Dernière intervention 16 décembre 2005
18 mai 2003 à 01:16
Monsieur elchevive,
Il ç'est pas possible ce que vous me dites là... "En fait, seuls +,-,*,/,²,sin,cos,tan,e et pi qui fonctionnent pico bello dans le traceur, mais pour le reste...."
Mon parser fonctionne tres bien, il faut juste bien s'en servir...

Il faut utiliser soit Evaluate() toute seule, soit Eval avec un try except.

for i := 0 to Length(tab) - 1 do
try
tab[i,2] := Eval(fEnter.fx.text,'x', cpt/10);
except
tab[i,2] := 0;
end;

sinon il faut voir la démo.
elchevive Messages postés 3 Date d'inscription samedi 22 février 2003 Statut Membre Dernière intervention 6 janvier 2005
29 avril 2003 à 17:48
Merci pour le coup de pouce, mais j'ai néanmoins encore quelques problèmes, y a pas mal de commande du parser qui ne fonctionne pas et provoque une erreur fatale.

tab[i,2] := Eval(fEnter.fx.text,'x', cpt/10); // dans une boucle...

En fait, seuls +,-,*,/,²,sin,cos,tan,e et pi qui fonctionnent pico bello dans le traceur, mais pour le reste....

Merci d'avance pour le coup de pouce !!
cs_ZED Messages postés 57 Date d'inscription dimanche 14 avril 2002 Statut Membre Dernière intervention 16 décembre 2005
7 avril 2003 à 03:23
A votre service :))
amiga68 Messages postés 54 Date d'inscription dimanche 23 février 2003 Statut Membre Dernière intervention 21 décembre 2009
31 mars 2003 à 07:03
Merci, Ô grand ZED !
cs_ZED Messages postés 57 Date d'inscription dimanche 14 avril 2002 Statut Membre Dernière intervention 16 décembre 2005
23 mars 2003 à 05:20
C'est réglé mtn
amiga68 Messages postés 54 Date d'inscription dimanche 23 février 2003 Statut Membre Dernière intervention 21 décembre 2009
2 mars 2003 à 20:34
Petit plantage pour 2 Pi ou 2 PI, mais pas pour 2 pI ou 2 pi
cs_ZED Messages postés 57 Date d'inscription dimanche 14 avril 2002 Statut Membre Dernière intervention 16 décembre 2005
23 févr. 2003 à 02:14
Par exemple:

var
R, Valeur: Real;

begin
...
X := 5.125;
R := Eval('5x+2/(2sin(x - pi/5))-9', 'x', Valeur);
...
end;

ici le parser remplace l'identificateur 'X' par valeur.
elchevive Messages postés 3 Date d'inscription samedi 22 février 2003 Statut Membre Dernière intervention 6 janvier 2005
22 févr. 2003 à 19:59
C'est pas mal du tout !!!
J'ai juste une tite question, comment je pourrais l'utiliser avec une variable (par ex X) au lieu d'une valeur immédiate ?
Merci d'avance.
cs_ZED Messages postés 57 Date d'inscription dimanche 14 avril 2002 Statut Membre Dernière intervention 16 décembre 2005
6 févr. 2003 à 23:30
Hum,
Effectivement!!! Merci d'avoir remarqué :)
C'est corrigé.
cs_MAURICIO Messages postés 2106 Date d'inscription mardi 10 décembre 2002 Statut Modérateur Dernière intervention 15 décembre 2014 5
31 janv. 2003 à 11:18
Désolé mais ça plante pour :
-2.36*2 (il fait 236*2)
Il semblerait que personne n' ai vu ce problème donc voilà
cs_ZED Messages postés 57 Date d'inscription dimanche 14 avril 2002 Statut Membre Dernière intervention 16 décembre 2005
10 janv. 2003 à 13:24
'légibilité' ? je crois entendre Lisibilité...
C'est vrai que le TIdentifier serait plus lisible. Mais ce n'est pas un drame. le programme fonctionne correctement (jqa maintement lol).

Si quelqu'un est tenté (pas moi), il pourrait en faire un programme de maths qui étudie les fonctions, représentation graphique, integrale, système d'équations... ect.

Bon coding...
@+
RuineBabine Messages postés 1 Date d'inscription jeudi 9 janvier 2003 Statut Membre Dernière intervention 9 janvier 2003
9 janv. 2003 à 02:43
Que les TIdentifier soient plus vite que les Integers n'a pas vraiement beaucoup d'importance ici car le code est suffisamment petit pour que cette différence se chiffre et terme de nanosecondes de plus ou moins.

Je suis plus partisan d'améliorer la légibilité du code dans un tel cas comme le disais Delphiprog ci-haut. Le gain sera alors calculable en précieuses secondes, que dis-je en minutes de temps sauvé à entretenir ce code.
cs_ZED Messages postés 57 Date d'inscription dimanche 14 avril 2002 Statut Membre Dernière intervention 16 décembre 2005
6 janv. 2003 à 23:18
Est ce vrai que Delphi est plus rapide dans les traitements des integer que ceux des Bytes?

Une autre question que je me pose.

@+
cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
6 janv. 2003 à 22:00
"Pour le TIdentifier... je crois qu'il faut une autre function pour reconnaitre chaque identifier..."
La fonction Ord suffit pour déterminer la position ordinale.
C'est curieux, j'avais lu l'inverse, comme quoi les type énumérés étaient plus efficaces. J'en veux pour preuve la mémoire pour stocker un type ordinal qui ne peut prendre qu'une valeur entre 0 et 255, un seul octet suffit donc pour le stocker.
Tandis qu'un Integer est stocké sur 32 bits, soit 4 octets.
Quelqu'un pourrait-il nous éclairer ou nous donner des références ?
cs_ZED Messages postés 57 Date d'inscription dimanche 14 avril 2002 Statut Membre Dernière intervention 16 décembre 2005
6 janv. 2003 à 12:16
Merci,
Pour les types énumérés, j'ai lu qq part que ça prends plus de memoire et de cpu qu'il n'en faut pour determiner une cardinalité.. donc j'ai opté pour ce qui est moins pénible pour l'execution.
Pour le TIdentifier... je crois qu'il faut une autre function pour reconnaitre chaque identifier... ce qui est deja fait par une boucle for. je pense que c'est optimisé comme ça.

Mais bon, merci poure le conseil.

@+
cs_Dalamar Messages postés 63 Date d'inscription samedi 22 décembre 2001 Statut Membre Dernière intervention 22 décembre 2003
6 janv. 2003 à 02:04
Super programme. 10/10
cs_Delphiprog Messages postés 4297 Date d'inscription samedi 19 janvier 2002 Statut Membre Dernière intervention 9 janvier 2013 32
5 janv. 2003 à 23:31
Pas mal !
Pour faciliter la lecture du code, j'aurais employé un type énuméré pour les différents 'Identifiers' plutôt que de déclarer un tableau de constantes de 0..12.
Genre :
TIdentifiers = (IdE, IdPi, IdSin, IdCos, IdTan, IdArcsin, IdArccos, IdArctan, IdExp, IdLn, IdLog, IdSqrt, IdInt);
et après :
Const
Identifiers : array[TIdentifiers] of string =(....)
Puis dans la procédure Factor, au lieu de :
for i := 0 to High(Identifiers) do
if Identifiers[i] = S then
begin
case i of
0 : Result := Exp(1);
1 : Result := Pi;
j'inscrirais :
for i := Ide to IdInt do
if Identifiers[Ord(I)] = S then
begin
case i of
IdE : Result := Exp(1);
IdPi : Result := Pi;
etc.
Mais bon, c'est génial comme çà.
Félicitations.
Rejoignez-nous