Accueil > > > CALCULER UNE OPERATION PRESENTE DANS UNE STRING (GESTION DES NOMBRES A VIRGULES)
CALCULER UNE OPERATION PRESENTE DANS UNE STRING (GESTION DES NOMBRES A VIRGULES)
Information sur la source
Description
Ce code permet de calculer une operation basique presentent dans une chaine de caractere, comme par exemple (3*5(10-2))/10 (qui renvoi 12) Cependant il ne prend pas en compte les priorité de multiplications et de division, et donc 5+3*2 revien pour lui à 8*2 (pour lui faire comprendre faut faire 5+(3*2)) il gere aussi les float (type single), donc 3*3.33333333333 = 10 ou preske :P je mets pas de zip, il suffit de faire un copier coller dans un fichier
Source
- (*--------------------------------------------//
- Calculatrice de chaines (resultat a virgule)
- Par anK (legere modif. de Bestiol :))
- Bug(s): lorsqu'on divise par 0... :D
- //--------------------------------------------*)
-
-
- unit Unit1;
-
- interface
-
- uses strUtils,sysUtils;
-
- type
- TOperation=(loAdd,loSub,loMul,loDiv);
-
- function CalculStr(Str:String):Single;
-
- const
- Niveau_Parentheses=15;
-
- implementation
-
- function SimplifyStr(Str:string):string;
- const
- Smpl: Array[0..3]Of String = ('++', '--', '+-', '-+'); //: Tableau des doublons à simplifier
- SmplPar: Array[0..3]Of String = ('+' , '+' , '-' , '-');//: Par quoi il faut les remplacer
-
- var i: Integer;
-
- begin
- //ça bug encore si il y a --- ou +++ ect... mais a part ça c nikel ;)
- //Plus maintenant ! ;o)
- Result := Str;
-
- for i := Low(Smpl) to High(Smpl) do
- While Pos(Smpl[i], Result) > 0 do
- Result := AnsiReplaceStr(Result, Smpl[i], SmplPar[i]);
-
- Result := AnsiReplaceStr(Result, '*(', '(');
- Result := AnsiReplaceStr(Result, '()','');
- Result := AnsiReplaceStr(Result, ' ',''); //On comble les trous!
- Result := AnsiReplaceStr(Result, '.',','); //Les . sont transformés en ,
- end;
-
- function CalculStr(Str:String):Single;
- var
- I,J:integer;
- LastOperande: TOperation;
- zPar: array[0..Niveau_Parentheses] of single; //Profondeur des parentheses
- tPar: array[1..Niveau_Parentheses] of TOperation; //Type liason entre la parenthese et sa superieure
- PeC: 0..Niveau_Parentheses; //Parenthese en Cours
- fstOp: boolean; //Premier operateur
- ActuNombre: boolean; //Si actuellement il y a un nombre...
- TailleNombre: Word;
- DebutNombre: Word;
- StringTemp: string;
- DejaVirgule: boolean; //Si le nombre a deja une virgule...
-
- procedure CalculUneOperation;
- var Nombre:single;
- begin
- Nombre:=StrtoFloat(Copy(StringTemp,DebutNombre,TailleNombre));
- case LastOperande of
- loAdd:
- zPar[PeC]:=zPar[PeC]+Nombre;
- loSub:
- zPar[PeC]:=zPar[PeC]-Nombre;
- loMul:
- zPar[PeC]:=zPar[PeC]*Nombre;
- loDiv:
- zPar[PeC]:=zPar[PeC]/Nombre;
- end;
- end;
-
- procedure StopNombre;
- begin
- DejaVirgule := False;
- ActuNombre := False;
- end;
-
- procedure InitParenthese;
- begin
-
- end;
-
- const
- Nombre = ['0'..'9']; //On a dans nombre aussi le '.', mais il est comptabilisé differement :)
- Signe = ['+','-','*','/'];
- Parenthese = ['(',')'];
- begin
- //-------------Initialisation-----------------
- LastOperande := loAdd;
- fstOp := True;
- PeC := 0;
- zPar[0] := 0;
- ActuNombre := False;
- DejaVirgule := False;
- //--------------------------------------------
- StringTemp := SimplifyStr(Str); //Simplification des calculs (++ devient + ect...)
- for I:=1 to Length(Str) do //Debut de la boucle
- begin
-
- //-------------Les Nombres -------------------
- if StringTemp[I] in Nombre then
- begin
- if not ActuNombre then //Si un nombre n'est pas deja "Lancé"
- begin
- //On le "lance"
- ActuNombre := True;
- DebutNombre := I;
- fstOp:=False;
- end;
- end;
- //--------------------------------------------
-
- //-------------La virgule --------------------
- if StringTemp[I] = ',' then
- begin
- if (not DejaVirgule) and ActuNombre then
- begin
- //On rajoute la virgule au nombre deja lancé
- DejaVirgule:=True; // =)
- end else begin
- //ERREUR dans la string meme...
- end;
- end;
- //--------------------------------------------
-
- //---------Parentheses ouvertes---------------
-
- if StringTemp[I] = '(' then
- begin
- if ActuNombre then//Si ActuNombre = True alors on coupe le nombre...
- begin
- TailleNombre := I-DebutNombre;
- ActuNombre := False;
- CalculUneOperation; //On calcul la derniere operation
- inc(PeC);
- zPar[PeC] := 0; //on reinitialise l'interieur de la parenthese
- //Donc si il y a un nombre k(x) on a k*x
- tPar[PeC] := loMul;
- //zPar[PeC] := 0;
- //Comme dans toute parenthese, le FirstOperateur=true, et on commence par un add
- LastOperande := loAdd;
- fstOp := True;
- end else
- begin
- inc(PeC);
- zPar[PeC] := 0; //on reinitialise l'interieur de la parenthese
- tPar[PeC] := LastOperande;//Le dernier operateur avant la parenthese
- LastOperande := loAdd;
- fstOp := True;
- end;
- end;
-
- //---------Parentheses fermé---------------
-
-
- if StringTemp[I] = ')' then
- begin
- //On s'assure la finalisation du dernier nombre de la parenthese
- if ActuNombre then
- begin
- TailleNombre:=I-DebutNombre;
- CalculUneOperation; //On finalise si jamais il resté un nombre...
- end;
-
- case tPar[PeC] of //On mets à jour la parenthese inferieur
- loMul:zPar[PeC-1]:=zPar[Pec-1]*zPar[Pec];
- loAdd:zPar[PeC-1]:=zPar[Pec-1]+zPar[Pec];
- loSub:zPar[PeC-1]:=zPar[Pec-1]-zPar[Pec];
- loDiv:zPar[PeC-1]:=zPar[Pec-1]/zPar[Pec];
- end;
- if ActuNombre then//Si ActuNombre = True alors on coupe le nombre...
- begin
- TailleNombre:=I-DebutNombre;
- ActuNombre:=False;
- CalculUneOperation; //On calcul la derniere operation
- //Donc si il ya un nombre k(x) on a k*x
- //LastOperande:=loMul; //Donc on multiplie ;)
- end;
- dec(PeC);
- end;
-
-
- //--------------------------------------------
-
-
- //-------------Le signe Plus-----------------
-
- if StringTemp[I] = '+' then
- begin
-
- if fstOp or (StringTemp[I-1] in ['*','/']) then //Si Premier calcul ou avant le - il y avait un * ou /
- begin
- //C'est le premier operateur, donc un debut de nombre...
- if StringTemp[I+1] in Nombre then //On debute un nombre...
- begin
- fstOp := False;
- ActuNombre := True;
- DebutNombre := (I+1);//Sans prendre en compte le +
- end;
- end;
-
- if ActuNombre then //Si un nombre est déja entrain d'etre lu
- begin
- ActuNombre := False; //On stoppe la lecture de ce nombre
- TailleNombre := I-DebutNombre;
- CalculUneOperation; //On calcul le dernier Operateur
- LastOperande := loAdd; //On change ce dernier operateur :)
- end;
-
- if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
- begin
- //A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
- //Donc pas de nombre à definir
- LastOperande := loSub; //On change seulement ce dernier operateur :)
- end;
-
- end;
-
- //--------------------------------------------
-
- //-------------Le signe Moins-----------------
-
- if StringTemp[I] = '-' then
- begin
-
- if ActuNombre then //Si un nombre est deja entrain d'etre lu
- begin
- ActuNombre := False; //On stoppe la lecture de ce nombre
- TailleNombre := I-DebutNombre;
- CalculUneOperation; //On calcul le dernier Operateur
- LastOperande := loSub; //On change ce dernier operateur :)
- end;
-
- if fstOp or (StringTemp[I-1] in ['*','/']) then //Si Premier calcul ou avant le - il y avait un * ou /
- begin
- //C'est le premier operateur, donc un debut de nombre...
- if StringTemp[I+1] in Nombre then //On debute un nombre...
- begin
- fstOp := False;
- ActuNombre := True;
- DebutNombre := I;
- end;
- end;
-
-
- if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
- begin
- //A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
- //Donc pas de nombre à definir
- LastOperande := loSub; //On change seulement ce dernier operateur :)
- end;
-
- end;
-
- //--------------------------------------------
-
- //-------------Le signe Multiplication--------
-
- if StringTemp[I] = '*' then
- begin
-
- if ActuNombre then //Si un nombre est deja entrain d'etre lu
- begin
- ActuNombre := False; //On stoppe la lecture de ce nombre
- TailleNombre := I-DebutNombre;
- CalculUneOperation; //On calcul le dernier Operateur
- LastOperande := loMul; //On change ce dernier operateur :)
- end;
-
- if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
- begin
- //A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
- //Donc pas de nombre à definir
- LastOperande := loMul; //On change seulement ce dernier operateur :)
- end;
-
- end;
-
- //--------------------------------------------
-
- //-------------La Division--------------------
-
- if StringTemp[I] = '/' then
- begin
-
- if ActuNombre then //Si un nombre est deja entrain d'etre lu
- begin
- ActuNombre := False; //On stoppe la lecture de ce nombre
- TailleNombre := I-DebutNombre;
- CalculUneOperation; //On calcul le dernier Operateur
- LastOperande := loDiv; //On change ce dernier operateur :)
- end;
-
- if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
- begin
- //A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
- //Donc pas de nombre à definir
- LastOperande := loDiv; //On change seulement ce dernier operateur :)
- end;
-
- end;
-
- //--------------------------------------------
-
- end;
-
- if ActuNombre then
- begin
- TailleNombre:=Length(StringTemp)-I;
- CalculUneOperation; //On finalise si jamais il resté un nombre...
- end;
- Result:=zPar[0]; //On fou dans result le nombre trouvé...
- end;
-
- end.
(*--------------------------------------------//
Calculatrice de chaines (resultat a virgule)
Par anK (legere modif. de Bestiol :))
Bug(s): lorsqu'on divise par 0... :D
//--------------------------------------------*)
unit Unit1;
interface
uses strUtils,sysUtils;
type
TOperation=(loAdd,loSub,loMul,loDiv);
function CalculStr(Str:String):Single;
const
Niveau_Parentheses=15;
implementation
function SimplifyStr(Str:string):string;
const
Smpl: Array[0..3]Of String = ('++', '--', '+-', '-+'); //: Tableau des doublons à simplifier
SmplPar: Array[0..3]Of String = ('+' , '+' , '-' , '-');//: Par quoi il faut les remplacer
var i: Integer;
begin
//ça bug encore si il y a --- ou +++ ect... mais a part ça c nikel ;)
//Plus maintenant ! ;o)
Result := Str;
for i := Low(Smpl) to High(Smpl) do
While Pos(Smpl[i], Result) > 0 do
Result := AnsiReplaceStr(Result, Smpl[i], SmplPar[i]);
Result := AnsiReplaceStr(Result, '*(', '(');
Result := AnsiReplaceStr(Result, '()','');
Result := AnsiReplaceStr(Result, ' ',''); //On comble les trous!
Result := AnsiReplaceStr(Result, '.',','); //Les . sont transformés en ,
end;
function CalculStr(Str:String):Single;
var
I,J:integer;
LastOperande: TOperation;
zPar: array[0..Niveau_Parentheses] of single; //Profondeur des parentheses
tPar: array[1..Niveau_Parentheses] of TOperation; //Type liason entre la parenthese et sa superieure
PeC: 0..Niveau_Parentheses; //Parenthese en Cours
fstOp: boolean; //Premier operateur
ActuNombre: boolean; //Si actuellement il y a un nombre...
TailleNombre: Word;
DebutNombre: Word;
StringTemp: string;
DejaVirgule: boolean; //Si le nombre a deja une virgule...
procedure CalculUneOperation;
var Nombre:single;
begin
Nombre:=StrtoFloat(Copy(StringTemp,DebutNombre,TailleNombre));
case LastOperande of
loAdd:
zPar[PeC]:=zPar[PeC]+Nombre;
loSub:
zPar[PeC]:=zPar[PeC]-Nombre;
loMul:
zPar[PeC]:=zPar[PeC]*Nombre;
loDiv:
zPar[PeC]:=zPar[PeC]/Nombre;
end;
end;
procedure StopNombre;
begin
DejaVirgule := False;
ActuNombre := False;
end;
procedure InitParenthese;
begin
end;
const
Nombre = ['0'..'9']; //On a dans nombre aussi le '.', mais il est comptabilisé differement :)
Signe = ['+','-','*','/'];
Parenthese = ['(',')'];
begin
//-------------Initialisation-----------------
LastOperande := loAdd;
fstOp := True;
PeC := 0;
zPar[0] := 0;
ActuNombre := False;
DejaVirgule := False;
//--------------------------------------------
StringTemp := SimplifyStr(Str); //Simplification des calculs (++ devient + ect...)
for I:=1 to Length(Str) do //Debut de la boucle
begin
//-------------Les Nombres -------------------
if StringTemp[I] in Nombre then
begin
if not ActuNombre then //Si un nombre n'est pas deja "Lancé"
begin
//On le "lance"
ActuNombre := True;
DebutNombre := I;
fstOp:=False;
end;
end;
//--------------------------------------------
//-------------La virgule --------------------
if StringTemp[I] = ',' then
begin
if (not DejaVirgule) and ActuNombre then
begin
//On rajoute la virgule au nombre deja lancé
DejaVirgule:=True; // =)
end else begin
//ERREUR dans la string meme...
end;
end;
//--------------------------------------------
//---------Parentheses ouvertes---------------
if StringTemp[I] = '(' then
begin
if ActuNombre then//Si ActuNombre = True alors on coupe le nombre...
begin
TailleNombre := I-DebutNombre;
ActuNombre := False;
CalculUneOperation; //On calcul la derniere operation
inc(PeC);
zPar[PeC] := 0; //on reinitialise l'interieur de la parenthese
//Donc si il y a un nombre k(x) on a k*x
tPar[PeC] := loMul;
//zPar[PeC] := 0;
//Comme dans toute parenthese, le FirstOperateur=true, et on commence par un add
LastOperande := loAdd;
fstOp := True;
end else
begin
inc(PeC);
zPar[PeC] := 0; //on reinitialise l'interieur de la parenthese
tPar[PeC] := LastOperande;//Le dernier operateur avant la parenthese
LastOperande := loAdd;
fstOp := True;
end;
end;
//---------Parentheses fermé---------------
if StringTemp[I] = ')' then
begin
//On s'assure la finalisation du dernier nombre de la parenthese
if ActuNombre then
begin
TailleNombre:=I-DebutNombre;
CalculUneOperation; //On finalise si jamais il resté un nombre...
end;
case tPar[PeC] of //On mets à jour la parenthese inferieur
loMul:zPar[PeC-1]:=zPar[Pec-1]*zPar[Pec];
loAdd:zPar[PeC-1]:=zPar[Pec-1]+zPar[Pec];
loSub:zPar[PeC-1]:=zPar[Pec-1]-zPar[Pec];
loDiv:zPar[PeC-1]:=zPar[Pec-1]/zPar[Pec];
end;
if ActuNombre then//Si ActuNombre = True alors on coupe le nombre...
begin
TailleNombre:=I-DebutNombre;
ActuNombre:=False;
CalculUneOperation; //On calcul la derniere operation
//Donc si il ya un nombre k(x) on a k*x
//LastOperande:=loMul; //Donc on multiplie ;)
end;
dec(PeC);
end;
//--------------------------------------------
//-------------Le signe Plus-----------------
if StringTemp[I] = '+' then
begin
if fstOp or (StringTemp[I-1] in ['*','/']) then //Si Premier calcul ou avant le - il y avait un * ou /
begin
//C'est le premier operateur, donc un debut de nombre...
if StringTemp[I+1] in Nombre then //On debute un nombre...
begin
fstOp := False;
ActuNombre := True;
DebutNombre := (I+1);//Sans prendre en compte le +
end;
end;
if ActuNombre then //Si un nombre est déja entrain d'etre lu
begin
ActuNombre := False; //On stoppe la lecture de ce nombre
TailleNombre := I-DebutNombre;
CalculUneOperation; //On calcul le dernier Operateur
LastOperande := loAdd; //On change ce dernier operateur :)
end;
if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
begin
//A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
//Donc pas de nombre à definir
LastOperande := loSub; //On change seulement ce dernier operateur :)
end;
end;
//--------------------------------------------
//-------------Le signe Moins-----------------
if StringTemp[I] = '-' then
begin
if ActuNombre then //Si un nombre est deja entrain d'etre lu
begin
ActuNombre := False; //On stoppe la lecture de ce nombre
TailleNombre := I-DebutNombre;
CalculUneOperation; //On calcul le dernier Operateur
LastOperande := loSub; //On change ce dernier operateur :)
end;
if fstOp or (StringTemp[I-1] in ['*','/']) then //Si Premier calcul ou avant le - il y avait un * ou /
begin
//C'est le premier operateur, donc un debut de nombre...
if StringTemp[I+1] in Nombre then //On debute un nombre...
begin
fstOp := False;
ActuNombre := True;
DebutNombre := I;
end;
end;
if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
begin
//A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
//Donc pas de nombre à definir
LastOperande := loSub; //On change seulement ce dernier operateur :)
end;
end;
//--------------------------------------------
//-------------Le signe Multiplication--------
if StringTemp[I] = '*' then
begin
if ActuNombre then //Si un nombre est deja entrain d'etre lu
begin
ActuNombre := False; //On stoppe la lecture de ce nombre
TailleNombre := I-DebutNombre;
CalculUneOperation; //On calcul le dernier Operateur
LastOperande := loMul; //On change ce dernier operateur :)
end;
if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
begin
//A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
//Donc pas de nombre à definir
LastOperande := loMul; //On change seulement ce dernier operateur :)
end;
end;
//--------------------------------------------
//-------------La Division--------------------
if StringTemp[I] = '/' then
begin
if ActuNombre then //Si un nombre est deja entrain d'etre lu
begin
ActuNombre := False; //On stoppe la lecture de ce nombre
TailleNombre := I-DebutNombre;
CalculUneOperation; //On calcul le dernier Operateur
LastOperande := loDiv; //On change ce dernier operateur :)
end;
if not fstOp then if StringTemp[I-1]=')' then //Si le dernier caractere été un ')' alors...
begin
//A la difference avec ActuNombre=true, on a ici pas de nombre, mais une parenthese...
//Donc pas de nombre à definir
LastOperande := loDiv; //On change seulement ce dernier operateur :)
end;
end;
//--------------------------------------------
end;
if ActuNombre then
begin
TailleNombre:=Length(StringTemp)-I;
CalculUneOperation; //On finalise si jamais il resté un nombre...
end;
Result:=zPar[0]; //On fou dans result le nombre trouvé...
end;
end.
Conclusion
exemple d'utilisation: ShowMessage(Floattostr(CalculStr('8/10')));
Si jamais des bugs apparaissent (et il doit y en avoir) merci de me le dire :)
Sources du même auteur
Sources de la même categorie
Commentaires et avis
|
Derniers Blogs
UNE JOLIE-HORLOGE ET PAS QU'UN PEU !UNE JOLIE-HORLOGE ET PAS QU'UN PEU ! par neodante
Pour les possesseurs d'iPhone, ça y est Bijin Tokei - qui se traduit littéralement en Français par " Jolie Horloge " - est arrivé et GRATUITEMENT s'il vous plaît ! Après la version Tokyo, Hokkaido, night club, racing, Gal, "pour les mademoiselles'", . voi...
Cliquez pour lire la suite de l'article par neodante TECHDAYS PARIS 2010 : CONNECTEZ VOS DONNéES à SHAREPOINT 2010 AVEC LES BUSINESS CONNECTIVITY SERVICESTECHDAYS PARIS 2010 : CONNECTEZ VOS DONNéES à SHAREPOINT 2010 AVEC LES BUSINESS CONNECTIVITY SERVICES par ROMELARD Fabrice
Animé par: Gaetan Bouveret et Julien Chomarat Business Connectivity Services (BCS) est dans SharePoint 2010 la version 2 de Business Data Catalog (BDC dans SharePoint 2007). Il s'agit de la solution permettant de visualiser des données provenan...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice [DIVERS] SUIVRE VOS SéRIES PRéFéRéS SUR LA TOILE[DIVERS] SUIVRE VOS SéRIES PRéFéRéS SUR LA TOILE par orion
Comme de nombreux geek, je suis un grand amateur de série TV et je rate régulièrement des épisodes de mes séries préférés. Une solution s'offre à vous avec ce merveilleux site : Tv Gorge - www.tvgorge.com Moteur de recherche à l'appui, vous pouvez ...
Cliquez pour lire la suite de l'article par orion TECHDAYS PARIS 2010 : LA BI DANS SHAREPOINT 2010TECHDAYS PARIS 2010 : LA BI DANS SHAREPOINT 2010 par ROMELARD Fabrice
Animé par: Vincent Bellet et Baptiste Giraudier La BI dans SharePoint 2010, Les nouveaux services d'application dans SP2010 et SQL Server Reporting services 2008 R2. La BI dans SharePoint est généralisée pour tous afin de permettre à tous les coll...
Cliquez pour lire la suite de l'article par ROMELARD Fabrice
Logiciels
DB-MAIN (9.1.0)DB-MAIN (9.1.0)DB-MAIN is a data-modeling and data-architecture tool. It is designed to help developers and anal... Cliquez pour télécharger DB-MAIN Xilisoft DPG Convertisseur (5.1.37.0120)XILISOFT DPG CONVERTISSEUR (5.1.37.0120)Xilisoft DPG Convertisseur offre aux fans de Nintendo DS une bonne solution leur permettant de dé... Cliquez pour télécharger Xilisoft DPG Convertisseur GraphicsGale (2.01.01)GRAPHICSGALE (2.01.01)GraphicsGale est un logiciel de PixelArt avec de nombreuse fonctionnalités permettant de réalisé ... Cliquez pour télécharger GraphicsGale Architecte 3D (Platinum 2010)ARCHITECTE 3D (PLATINUM 2010)Architecte 3D Platinium vous permet de concevoir facilement les plans votre future maison, de l'é... Cliquez pour télécharger Architecte 3D TeamViewer 5 (TeamViewer 5)TEAMVIEWER 5 (TEAMVIEWER 5)Dépanner un ami,expliquer une manipulation devient un jeu d'enfant.
Prise en main d'un autre ord... Cliquez pour télécharger TeamViewer 5
|