Solved

Implementing math functions

Posted on 1998-04-28
19
314 Views
Last Modified: 2010-04-03
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
0
Comment
Question by:Edo082297
  • 8
  • 5
  • 4
  • +1
19 Comments
 
LVL 8

Expert Comment

by:ZifNab
ID: 1338642
So you want :

 A Formula Parser?

 AND

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

Correct?

Regards, Zif.
0
 
LVL 5

Expert Comment

by:inter
ID: 1338643
Hi friends,

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
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 1338644
Yo Inter,

Seems both interesting, ... and learnfull.

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

Regards, ZiF.
0
 
LVL 5

Expert Comment

by:inter
ID: 1338645
Hi,
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
0
 
LVL 1

Expert Comment

by:Greedy
ID: 1338646
the Rx libraries is said to have something called TRxMathParser I only know about it from these pages
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.

0
 
LVL 5

Expert Comment

by:inter
ID: 1338647
He, he :-)
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

0
 
LVL 1

Author Comment

by:Edo082297
ID: 1338648
Hello Igor, Zif and Greedy
  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
 
0
 
LVL 5

Expert Comment

by:inter
ID: 1338649
Hi,
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
0
 
LVL 1

Author Comment

by:Edo082297
ID: 1338650
Hi Igor
   Thankyou for your stellar effort. Post your last comments as an answer, I will award you with the points.

Regards,
Edo
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 5

Expert Comment

by:inter
ID: 1338651
Hi,
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
0
 
LVL 1

Expert Comment

by:Greedy
ID: 1338652
I'd like to see how you did it...
flicky@frottage.com
Thanks

0
 
LVL 5

Expert Comment

by:inter
ID: 1338653
Hi to all,
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 (not reliable nowadays)
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 1338654
Igor, I want to look at it too .... (as always) Tom.Deprez@uz.kuleuven.ac.be
0
 
LVL 1

Author Comment

by:Edo082297
ID: 1338655
Hi Inter
  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
0
 
LVL 8

Expert Comment

by:ZifNab
ID: 1338656
Edo, I send it to you, because it can be that inter isn't at his office... Good luck ...
0
 
LVL 1

Author Comment

by:Edo082297
ID: 1338657
Hey
  Thanks, Zif


0
 
LVL 5

Expert Comment

by:inter
ID: 1338658
Hi there,
I just want to ask if it fits your needs. Any suggestions from any friend are wellcome.
Regards, Igor
0
 
LVL 1

Author Comment

by:Edo082297
ID: 1338659
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
0
 
LVL 5

Accepted Solution

by:
inter earned 150 total points
ID: 1338660
Thanks friend,
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
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
It is a freely distributed piece of software for such tasks as photo retouching, image composition and image authoring. It works on many operating systems, in many languages.
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

759 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now