The Calculation class allows the creation of objects able to perform complex calculations.
Example, constructing a Calculation using a String:
// may you want to calculate hypotenuses - sprt(a^2+b^2) = hypotenuse
Calculation pythagoras = new Calculation("(n^2)+(n^2)r(2)");
// you'd do a calculation like this;
double someHypotenuse = pythagoras.calc(3,4);
Formula class holds a Calculation object and instances of Formula class is able to do between 0 and n-length series calculations on input factors supplied as Double arrays.
A description should be made, but I can't be bothered right now, so here is an example:
Example:
Formula formulaEx = new Formula("(n*n)^(n+1)");
double[] results = formulaEx.computeSeries(
new Double[]{2d,3d,4d}, // factor n (1st n)
new Double[]{2d,3d,4d}, // factor n (2nd n)
new Double[]{2d,3d,4d}); // factor n (3rd n);
If you need to do a single calculation at a time, use a Calculation class object instead.
There are certain special rules on how calculations can be put together: read on (or see class). For rules on how to form a calculation properly, see the top of that class - or read on).
You can check out the examples in the Test_TextCalculation-class or the examples of how to use the builder pattern in CalculationTest-class.
/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~*\
#
First character must be a '('. Last character must be a ')'.
Second char of a calc string must be either a number (marking a constant), or an n (marking a variable input, which can then be supplied when running calc(double...) to do a calculation).
In general a calculation can consist of factors (constants or input variables) and operators;
Implemented operators are: / , * , - , + , r (root), p (pow), m (mod)
All implemented operators are accept two factors and return a double.
Single expressions are written between parenthesis; a single expression is any combination of factors and operators that can be resolved going strictly left to right.
Negative constants are prefixed with ' ~ ' (and NOT - )
Unlike normal java math notation, this is a possible single expression: (n-n*n)
In customary math notation you'd write that like: (n-n)*nA few examples:
Declaration string:
TextCalculation syntax: 4*~5/5 "(4*~5/5)"
Orinary math syntax: ((4*-5)/5)
TextCalculation syntax: 1+3*5/6 "(1+3*5/6)"
Orinary math syntax: (((1+3)*5)/6)
TextCalculation syntax: 4*5-6*5p2+1 "(4*5-6*5p2+1)"
Orinary math syntax: ((((4*5)-6)*5)pow2)+1)
TextCalculation syntax: n^2)+(n^2)r(2 "(n^2)+(n^2)r(2)"
Orinary math syntax: sqrt((a^2)+(b^2))
Be aware that in all examples, factors that you need to be input/ method parameter variables are written as ' n '.
Binding operators is my term of art for operators placed outside parenthesis: a binding operator is any operator mentioned above; like above, each operator is resolved strictly going from left to right. A binding operator acts on the two evaluated expressions immediately adjacent to it.
A binding operator is written as ')' 'operator' '('
Pattern : ) [/*-+rm] (
TextCalculation syntax: 5+6*5)*(5/5 <- here )*( is a binding operator
Orinary math syntax: ((5+6)*5)*(5/5)
You can get the pythagorean sentence to calculate the hypotenuse of a right angled triangle like:
Calculation hypotenuse = new Calculation("(n^2)+(n^2)r(2)");
// Or %-increase from A to B:
Calculation increase = new Calculation("(n/n-1*100)");
.\~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/.
#
Definitions:
A) A single expression consist of factors (numbers) and operators; the term is here used so that an expression is any set of factors and operators that can be evaluated/calculated going from left to right (see rules).
B) A binding operator is any operator +, -, /, *, mod, pow or root acting on two expressions that could be written in seperate parenthesis, like (2) * (5+7) where * is a binding operator.
Ba) Binding operators bind evaluated expressions through its operation upon them (and the produced result)
// To turn an operater into a binding operator, call expression() before calling the <operator>()
// Declaring a + operator in a calculation as a binding operator is done like this:
CalcBuilder...().expression().plus(). .. // string-constructor: )+(
// And just to hammer home the principle; a - can be declared as binding like:
...().expression().minus(). .. // string: )-(
Evaluation of calculation in short:
A. First all (single) expressions are resolved (binding operators are not).
B. Second the 'un-bound' expressions are interpreted as belonging to one single expression consisting of the results of the previous calculations (first round) AND the binding operators; it is resolved/calculated, and there is your answer...
A possibly helpful example:
Imagine a Calculation object declared like this:
Calculation pyt = new Calculation("(nr2)+(n/2)");
Tip: To get a view of how the Calculation works internally, call logToConsole(true) on a Calculation object, and it will print its process to the console (when calling calc(double...)).
There are a few rules:
1. Expressions are evaluated left to right:
Operators act on the running total/result of current expression with the next single factor (for a binding operator, this is the next whole expression)):
[next runningResult] = <\runningResult \operator \nextFactor>
Practical example:
This is a possible single expression: ((4+6)/5)*2
// expression can be declared as a Calculation like this:
Calculation calcula = new Calculation.CalcBuilder().create().
plus().
divideBy().
multiply().
build();
// or, using constructor taking a string:
Calculation calculb = new Calculation("(4+6/5*2)");
NOT a possible single expression: (2*((4+6)/5)) (it is two)
// it can be/would need to be declared like following:
Calculation calculc = new Calculation.CalcBuilder().create().
expression().multiply().
plus.
divideBy().
build();
// or, using constructor taking a string:
Calculation calculd = new Calculation("(2)*(4+6/5)");
// Explanation: (2*((4+6)/5)) is not a single expression, but it is very possible
// to declare it, as immidiately above, using the expression() method to indicate
// the separation of the two calculations.
// SO, (2*((4+6)/5)), expressed through the Calculation class is two expressions, not one.
// And that calculation can be declared using string "(2)*(4+6/5)".
2. A calculation with binding operators can have nested binding operators ONLY IF the nests can be resolved with the second calculation round (see above) being made strictly going left to right. (Internally, the 'second round' of calculation - where the binding operators get to operate on the expressions evaluated in the 'first round')
3. If an ' expression().<'binding operator'>() ' is placed first in the declaration of a calculation, this it is interpreted to mean that the binding operator's left operand is a single number/factor, and that the right operand is an (evaluated) expression.
#
If you decide to work directly with the CalcBuilder this is how you might declare+initialize the most famous theorem of Pythagoras as a Calculation:
// WITHOUT constants:
// Length of hypotenuse: length = ((x^y)+(z^v))root(w)
Calculation pytagoras = new Calculation.CalcBuilder().
create(). // performs baseline initialization on builder-object
pow(). // analogous to: "(n^n
expression().plus(). // analogous to: )+(
pow(). // analogous to: n^n
expression().root() // analogous to: )root(n)"
.build(); // returns the finished Calculation object
System.out.println("sprRoot(5^2 + 4^2) = " + pytagoras.calc(5, 2, 4, 2, 2));
System.out.println("sprRoot(3^2 + 4^2) = " + pytagoras.calc(3, 2, 4, 2, 2));
// WITH constants:
// Length of hypotenuse: length = ((x^2)+(y^2))root(2)
Calculation pytagoras = new Calculation.CalcBuilder().
create(). // performs baseline initialization on builder-object
pow().constant(2) "(n^2
expression().plus(). )+(
pow().constant(2) n^2
expression().root().constant(2) )root(2)"
.build(); // returns the finished Calculation object
// which is then called with only two arguments, so:
System.out.println("sprRoot(5^2 + 4^2) = " + pytagoras.calc(5, 4));
System.out.println("sprRoot(3^2 + 4^2) = " + pytagoras.calc(3, 4));
// Note:
// There is no square root, but the general root-function;
// so ' square root of x ', is pseudo-written like ' x root 2 ').
There are probably a few more rules that I didn't realize yet, sorry. This is a work in progress and I'm not a mathematician.
#
Goals:
.\~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/.
The major goal for next iteration is the integration of all relevant
operators from java.lang.Math into Calculation/CalcBuilder/TextCalculation classes.
Which means the introduction of unary operators.
.\~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/*~:~* \~/.
All comments and feedback is welcome; this is work in progress, and I'd love great ideas.