This course will introduce you to C++ 11 and teach you about syntax fundamentals.

Hi All

I would like some ideas on how to get Delphi to evaluate mathematical functions. Suppose I define a function f(x) = x^2. I would like to 'send' f(2) and get 4 back. Now, this is harder then it would seem, because I need to implement _user-defined_ functions at runtime. The user will be able to define a function, say, Sqrt(E^(2*x) + Ln(4*Pi) - log(23*x^3)), in a TEdit, and I have to manipulate the result of the function over a given interval, for many, many values.

Yes, I know of the Poly function, but one of my main problems is that even if I succeeded in translating a function into Delphi using the arithmetic routines, I don't know how I could store the function so that I don't need to keep _re-translating_ it for each iteration. E.G. If the user defined x^2, and I need to calculate x^2 for 2500 values, how can I store the function as an object so that I don't keep translating what is in the TEdit into a function, replacing my x-value, and re-calculating?

Those of you who program in Java may know of the Function method, where you can assign a veritable beast, and evaluate the funtion at given points. I need a Delphi equivalent, or a component (which I have looked for), or a new way of thinking about a solution.

Many thanks if you've read this far :)

Edo

I would like some ideas on how to get Delphi to evaluate mathematical functions. Suppose I define a function f(x) = x^2. I would like to 'send' f(2) and get 4 back. Now, this is harder then it would seem, because I need to implement _user-defined_ functions at runtime. The user will be able to define a function, say, Sqrt(E^(2*x) + Ln(4*Pi) - log(23*x^3)), in a TEdit, and I have to manipulate the result of the function over a given interval, for many, many values.

Yes, I know of the Poly function, but one of my main problems is that even if I succeeded in translating a function into Delphi using the arithmetic routines, I don't know how I could store the function so that I don't need to keep _re-translating_ it for each iteration. E.G. If the user defined x^2, and I need to calculate x^2 for 2500 values, how can I store the function as an object so that I don't keep translating what is in the TEdit into a function, replacing my x-value, and re-calculating?

Those of you who program in Java may know of the Function method, where you can assign a veritable beast, and evaluate the funtion at given points. I need a Delphi equivalent, or a component (which I have looked for), or a new way of thinking about a solution.

Many thanks if you've read this far :)

Edo

Experts Exchange Solution brought to you by

Enjoy your complimentary solution view.

Get every solution instantly with premium.
Start your 7-day free trial.

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

PARSING

-------

I just try to give an idea how these are handled. The Expression Evaluation is a key subject in compiler or interpreter design. In order to understand the expression parsing we should know about the common expression types known as INFIX, PREFIX, POSTFIX. For example :

INFIX : x + y (This is what we can read, it is hard for computers)

PREFIX : +xy (This is more proper for computer)

POSTFIX: xy+ (This is also proper for computer)

In evaluating the expression the INFIX form is the least suitable for computer. If we want to compute fast we should convert it to PREFIX or POSTFIX. Why ? Because the PREFIX and POSTFIX forms requires a single stack to evaluate, and the computer simply push pop the tokens and evaluate in a SINGLE PASS. However in INFIX form we should tokenize the expression each time we evaluate then add paranthesis, evalueate etc.

At this point inorder to correctly evaluate and expression we should have a OPERATOR PRECEDENCE table. You can even search for it from the Delphi help.

WHAT COMPILER DOES

------------------

After converting into a proper form the compiler just places the computation code by making relative reference to the DATA and VARIABLES you specified. This is complex esspecially for optimizing compilers, for example whenever the expression is form of product of sums(ie.e (x+y)*(z+q)*..) it checks the zero condition for each sum then skip if 0.

SO

---

There are two choices we can implement and two factors:

1 - INTERPRETED : Convering expression to POSTFIX and store is in a string quickly parse and evaluate using a TStack class we write.

2 - COMPILED : Declare a modifiable code segment large enough to store the expression (Moderate: can be done in pascal) Parse it and write a cpu code (just like delphi does) which evaluates the result on the fly. And call it in a loop for the arguments. (Hard: can only be done using mixed code-both asm and pascal)

So what do you think?

Regards, Inter

Seems both interesting, ... and learnfull.

What about you EDO. You've to make the descission.

Regards, ZiF.

Again, there is a freeware full source component ( which is said to evaluate only 40% slover than compiled code). As frequent from:

http://sunsite.icm.edu.pl/delphi/ftp/d10free/parser10.zip

Take it and install. if you need to modify the source, we(plural-experts-, I do not like to speak like a king) can help you.

Cheers, Igor

http://www.officeauto.com/lounge/partner/rxlib/

http://www.officeauto.com/lounge/partner/rxlib/rxparser.htm

it says this

Accepted operators:

+ , - , * , /

The following functions are supported; it doesn't matter if you use lower or upper case:

Arctan, Cos, Sin, Tan, Abs, Exp, Ln, Log, Sqrt, Sqr, Int, Fraq.

it looks decent for trig stuff but if your doing diffEQ and you need it quick get something like Maple.

Hey Inter do you work for HP or something because that is how their caculaters work they call it reverse polish notation.

If you have problems getting the Rx libraries just post something here and I'll send them to you - they are free too.

No friend (not working for HP) I remember those from '441 - Algorithms and Data Structures with Pascal' or some lecture like that.

Anyway, the theory enlarges back to Automata theory(regular expressions, NFA, DFA, context-free/sensitive languages). Edo, If you really intended to learn a bit theory than seek in internet. There are a lot of lecture notes on the sites.

Regards, Igor

Thankyou for your comments. Sorry I didn't get back sooner; I have been terribly busy. I am going to check out the components that were suggested, although I don't think they'll be fast enough for my purposes (I'll have to try them to find out).

Igor, converting the expression to POSTFIX and storing it in a string for parsing using a derived TStack class sounds feasible and interesting; could you give me an idea of how to proceed, considering I couldn't find anything referencing POSTFIX in the on-line help? The second method you suggested also sounds interesting, but quite complex. Would you also suggest a list of keywords relating to Automata theory, regarding seeking a bit of theory?

Cheers All,

Edo

I try to writedown something for you tonight for converting from infix to postfix. There are several reference in internet esspecially lecture notes. Automata is quickly scanned, for example at:

http://cs-www.uchicago.edu/~odonnell/OData/Courses/CS221/Lecture-Notes/syntax.html

Or use the keywords

+"parse tree" +automata

OR

+"parse tree" +"lecture notes"

from www.infoseek.com

To succesfully understand the expression notation you'd better know about expression trees, or parse trees and tree traversal. Sorry, can not give more info, I have to leave

c.u

Igor

Thankyou for your stellar effort. Post your last comments as an answer, I will award you with the points.

Regards,

Edo

Excuse me, since my IP changes, there is a problem that I can have notification via email. Please those who want the code please give email addresses. It is not proper for this thread to post 700 lines (yes it took about 700 lines) of code with all the conversion and evaluation staff in it. So, let me email you the source, then we discuss and finalize it.

Regards,

Igor

To serve for ExpertsExchange, I try to describe the math expression evaluator. Here it is:

TEvaluator

-------------

properties

property Expression: string; Read/Write

property PostFix: string; Read only

methods

function AddVar( Name : String; var V):boolean;

function BeginEval: boolean;

function Evaluate : extended;

functions recognized by parser

ARCTAN| COS| SIN| TAN| ABS| EXP| LN| LOG| SQRT| SQR| INT| FRAC

operators recognized by parser

^ * / + -

THATS IT!

Since we require(or this is because I can not design it better) fast execution, there are some

restrictions imposed by the parser (although normal variable assignment is easy to add). Here I

should act tricky. You will see what I mean. Here is the general usage:

Say we have : f(A,B,C,D,E) = cos(A) + sqr(B^sin(A)/C+ln(D)*E)

The following is the real delphi code that executes the function above 10000 times with the

random values with only parsing it ONCE:

//*************START******

var

T: TEvaluator;

A, B, C, D, E: double;

i : integer;

begin

Randomize;

T := TEvaluator.Create;

try

// 1 - Assign the string expression to expression.

// At this step all the convertions are done

// The evaluator only needs Variable references

T.Expression := 'cos(A) + sqr(B^sin(A)/C+ln(D)*E)';

// 2 - You MAY get the postfix representation (OPTIONAL) afterwards

Edit2.Text := T.PostFix;

// 3 - This is the trick. Here we say parser that for subsequent evaluations

// It will use the actual address of the variable 'A' when using computation

// with A. THE RESTRICTION I MEANT IS THIS!

T.AddVar('A', A); T.AddVar('B', B); T.AddVar('C', C);

T.AddVar('D', D); T.AddVar('E', E);

// 4 - Begin eval just checks if all the variables in the expression are assigned to values

// if that is the case it is ready for evaluation

if T.BeginEval then

for i := 1 to 10000 do

begin

A := Random; B := Random; C := Random;

D := Random; E := Random;

T.Evaluate;

end;

finally

T.Free;

end;

end;

//*************END********

If the variable passing above appears some of you weird, consider the following static

allocation:

1 - Tell your users that they can only use 'A' to 'Z'.

2 - Construct an array of Double

V : array['A'..'Z'] of Double;

3 - After T.Evaluate add all the vars with

for i := Ord('A') to Ord('Z') do

T.AddVar(Char(i), V[i]);

4 - The redundant variables are not important. That means if only A,B,C is used in expression

it is not an error to Add D also.

! YOU ARE WELCOME TO OFFER A MORE CLEVER SCEME AND I DO IMPLEMENT IT !

BencMark :

-------------

133Mhz Pentium, Nt4.0 : f(.) = cos(A) + sqr(B^sin(A)/C+ln(D)*E)

performs about 36K function evaluations/second

Any comment well come

Regards, (You remind me my university days, I work hard for it, may it please any one who use)

Igor

inter@kosgeb.tekmer.gov.tr

The benchmark is within the limits of speed I require. Post an answer whenever, you certainly deserve points for this most edifying ( ;-) to Greedy ) work. I look forward to working with the code.

Edo

egarson@hotmail.com

I just want to ask if it fits your needs. Any suggestions from any friend are wellcome.

Regards, Igor

You made such a killer effort, post 'HELLO' as an answer, I will award the points and we can kill this thread.

Thankyou one and all for sending me useful stuff and perpetuating stimulating discourse.

Regards,

Edo

I have been away for my exams, but return now. What do you think about publising the source in Delphi sites(I am always at standby for bug fixes and improvments). It is nice to work for friends,

Regards, Igor

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Delphi

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Experts Exchange Solution brought to you by

Enjoy your complimentary solution view.

Get every solution instantly with premium.
Start your 7-day free trial.

A Formula Parser?

AND

Something that ones the formula is parsed --> calculations are made...

Correct?

Regards, Zif.