- Step 1. Add the JitPack repository to your build file
Add it in your root build.gradle at the end of repositories:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
- Step 2. Add the dependency
dependencies {
compile 'com.github.ylfzq:Calculator:*'
}
Simple usage is:
System.out.println(
Calculator.getDefault().calcExpression("1+2*(3+4*6)/min(5, 2, PI)")
);
which outputs 28.0 as result.
You can print calculate steps to PrintStream by
System.out.println(
Calculator.getDefault()
.setCalcStepPrintStream(System.err) // print calculate steps to System.err
.calcExpression("1+2*(3+4*6)/min(5, 2, PI)")
);
the output is:
4.0*6.0=24.0
3.0+24.0=27.0
2.0*27.0=54.0
PI=3.141592653589793
min(5.0,2.0,3.141592653589793)=2.0
54.0/2.0=27.0
1.0+27.0=28.0
28.0
We call all operands, functions and constants as "CalcUnit". CalcUnit's hierarchy:
CalcUnit
|-- ConstantCalcUnit
|-- FunctionCalcUnit
|-- OperatorCalcUnit
|-- SingleOperandOperatorCalcUnit
|-- TwoOperandsOperatorCalcUnit
You can call Calculator.addCalcUnit(CalcUnit[])
to add custom implemented CalcUnit. For example:
Calculator.getDefault().addCalcUnit(new CalcUnit[] {
new ConstantCalcUnit("e", 2.718281828),
new ConstantCalcUnit("g", 9.8),
new FunctionCalcUnit("sqrt") { // define function named sqrt
@Override public Number doCalc(Number... vals) {
if (vals.length > 1) {
throw new IllegalArgumentException("sqrt() can only receive 1 param");
}
return Math.sqrt(vals[0].doubleValue());
}
},
new TwoOperandsOperatorCalcUnit("**", CalcUnitsImpl.CALC_LEVEL_MULTIPLY_DIVID + 1) {
@Override public Number doCalc(Number val1, Number val2) {
return Math.pow(val1.doubleValue(), val2.doubleValue());
}
}
});
// The first param is the constant name, the second param is the constant value
new ConstantCalcUnit("e", 2.718281828);
new FunctionCalcUnit("sqrt") { // define function named sqrt
@Override public Number doCalc(Number[] vals) { // the function params, you can throw if the param count is not correct
if (vals.length > 1) {
throw new IllegalArgumentException("sqrt() can only receive 1 param");
}
return Math.sqrt(vals[0].doubleValue());
}
}
There are 3 types of Operators: left-single-operand operator, right-single-operand operator, two operands operator.
// define a factorial operator "!", the second param true stands the operand is left to operator, otherwise is stands right operand.
public static final CalcUnit OPERATOR_FACTORIAL = new SingleOperandOperatorCalcUnit("!", true) {
@Override public Number doCalc(Number val) {
double mul = 1;
int a = val.intValue();
for (int i = 2; i <= a; ++i) {
mul *= i;
}
return mul;
}
};
Call setStackPrintStream(PrintStream)
or setCalcStepPrintStream(PrintStream)
on Calculator to print steps.
System.out.println(
Calculator.getDefault()
.setStackPrintStream(System.err)
.calcExpression("1+2*(3+4*6)/min(5, 2, PI)")
);
[]
[1.0]
[+]
[1.0]
[+]
[2.0, 1.0]
[*, +]
[2.0, 1.0]
[(, *, +]
[2.0, 1.0]
[(, *, +]
[3.0, 2.0, 1.0]
[+, (, *, +]
[3.0, 2.0, 1.0]
[+, (, *, +]
[4.0, 3.0, 2.0, 1.0]
[*, +, (, *, +]
[4.0, 3.0, 2.0, 1.0]
[*, +, (, *, +]
[6.0, 4.0, 3.0, 2.0, 1.0]
[*, +]
[27.0, 2.0, 1.0]
[/, +]
[54.0, 1.0]
[min, /, +]
[(, 54.0, 1.0]
[(, min, /, +]
[(, 54.0, 1.0]
[(, min, /, +]
[5.0, (, 54.0, 1.0]
[(, min, /, +]
[5.0, (, 54.0, 1.0]
[(, min, /, +]
[2.0, 5.0, (, 54.0, 1.0]
[(, min, /, +]
[2.0, 5.0, (, 54.0, 1.0]
[(, min, /, +]
[3.141592653589793, 2.0, 5.0, (, 54.0, 1.0]
[/, +]
[2.0, 54.0, 1.0]