Introduction
This article describes a simple yet extensible C++ class for performing arithmetic calculations. You can use it when you need to calculate an expression that isn't known at the compile time. Its primary use is, I guess, for calculator programs, and then - what ever you'd think its useful for.
The calculations are based on Reverse Polish Notation technique invented almost a hundred years ago - it was easiest to implement. You can find out more about RPN at http://www.calculator.org/rpn.html
How to use it
To use the class you just need to include an "calctypes.h" in your project and to create an object of this class where you'd like it to be. The demo Project is written with WTL 7.0 and the source code depends on WTL's CString
(located in "atlmisc.h") which is a serious flaw, generally speaking. You can look if it could be easily replaced with a MFC CString
, or maybe just a char*.
Then when you need to calculate something you just call the Calculate(LPSTR, LPSTR)
function with the expression as a first parameter and a variable list as a second. It will return the calculated value.
expression
should contain only numbers, operators and variables (which I believe is everything other then the previous two). Numbers consist of '0' thru '9' and a '.', operator labels are configured in "calctypes.h". You should try it yourself, I always used names like "x" and "y" for vars. An example "Sin(x+y-Pow(2 +Cos(x-y),x*y))". Note that I treat a parenthesis as an operator.
variablelist
is a semicolon separated list of equalities like this "x=12;y=31;z=2.3323" and there shouldn't be a trailing semicolon.
How to extend it
There is only a simple limited number of operators defined in "calctypes.cpp" and you will probably want to add something to your taste. All my effort while writing this class was to make it easy to implement new operators. You can create operators like "Indicator" or "Magnitude" or "Gradient" and others with this class. With a slight modification of the class you can even implement a different sets of operators which could be used when calculating an expression. The limit is that all operators should have no more then 3 arguments. If anyone knows an advanced technique that could be used to implement and "n" argument operators in my class, please let me know.
Now straight to the point. The code that calculates the expressions does not depend on defined operators in any way. You should do the following to add a new arithmetic operator to the calculator class:
Steps:
- Define a function that takes 3 pointers to doubles and returns a double.
It should conform to the following typedef
:
typedef double (*TThreeArgFnPtr) (double * in_pdArg1,
double* in_pdArg2 = NULL,double* in_pdArg3 = NULL);
You should place it in a "calctypes.cpp" file and it should look like that:
double Addition(double * in_pdArg1,double* in_pdArg2 = NULL,
double* in_pdDummy = NULL)
{
return *in_pdArg1 + *in_pdArg2;
}
- Then create a global object of structure
SOperator
for your newly added operator.
The structure's constructor takes 4 arguments - the first is the operators label, a string that will identify an operator in the expression, the second is its priority, the third is a number of operators arguments, and the last is a function that should be used for calculations (you just added it).
You should end up with something like this:
SOperator AdditionOperator(_T("+"),1,2,Addition);
Once you made it you need to place a pointer to newly declared operator in the array of operators, which is
SOperator* g_aUsualOperators[g_constNumberOfOperators] = ...
The last thing to do is to modify the g_constNumberOfOperators
variable declared in "calctypes.h"
You're done. I told you it'll be easy :) Use it freely, and don't hesitate to send feedback. Even critics. :)
TODO
There're however some real bad things about it:
- The code IS BUGGY. Sorry no time to polish it.
- Operators cant take more then 3 arguments. Anyone?
- Operator sets aren't implemented.
- Dependence on
CString
.
- Whachya say?? :)