During different calculations with decimal numbers in Java we come to problem with using primitive data types and their precision. Especially when we work with a double and we come across of losing precision. Another solution is to use BigDecimal, but still we have a problem of easy writing formula. JCalc open source API provides easy writing formula in Java and maintaining precision offered by the BigDecimal. This talk will cover basic JCalc usage and functionalities of API.
JavaCro'14 - JCalc Calculations in Java with open source API – Davor Sauer
1. Calculations in Java with open source APICalculations in Java with open source APICalculations in Java with open source APICalculations in Java with open source API
Author: Davor Sauer
www.jdice.org
2. Content
Calculations in Java- basics
Calculations in Java with JCalc
Comparison of complex calculation with plain Java and
Features
Questions
of complex calculation with plain Java and JCalc
3.
4. Calculations in Java-
Example: Simple calculation: If you pay $2.00 for a beer that costs $1.10,
how much changes do you get?
System.out.println(2.00 - 1.10); Answers:
a)
b)
c)
d)
gDecimal payment = new BigDecimal(2.00); Answers:gDecimal payment = new BigDecimal(2.00);
gDecimal cost = new BigDecimal(1.10);
ystem.out.println(payment.subtract(cost));
Answers:
a)
b)
c)
d)
=> 0.89999999991118215802998747...
gDecimal payment = new BigDecimal("2.00");
gDecimal cost = new BigDecimal("1.10");
ystem.out.println(payment.subtract(cost));
Answers:
a)
b)
c)
d)
- basics
Simple calculation: If you pay $2.00 for a beer that costs $1.10,
Answers:
.9
.90
0.899999999999
None of the above
Answers:Answers:
.9
.90
0.899999999999
None of the above
=> 0.89999999991118215802998747...
Answers:
.9
0.90
0.899999999999
None of the above
6. Calculations in Java-
Example: Simple calculation: If you pay $2.00 for a beer that costs $1.10,
how much changes do you get?
System.out.println(Calculator.builder().val(2.00).sub(1.10).
m p = new Num(2.00);
m c = new Num(1.10);m c = new Num(1.10);
tem.out.println(Calculator.builder().val(p).sub(c).calculate
m p = new Num("2.00");
m c = new Num("1.10");
tem.out.println(Calculator.builder().val(p).sub(c).setStripTrailingZeros
tem.out.println(Calculator.builder("2.00 - 1.10").setStripTrailingZeros
- basics
Simple calculation: If you pay $2.00 for a beer that costs $1.10,
().val(2.00).sub(1.10).calculate());
Answers:
a) 0.9
b) .90
c) 0.899999999999
d) None of the above
0.899999999999
d) None of the above
calculate()); Answers:
a) .9
b) .90
c) 0.899999999999
d) None of the above
setStripTrailingZeros(false).calculate());
setStripTrailingZeros(false).calculate());
Answers:
a) .9
b) 0.90
c) 0.89999999
d) None of th
0.9
0.89999999991118215802998747...
7. Complex example
Calculate fixed monthly payment for a fixed rate mortgage by Java
ecimal interestRate = new BigDecimal("6.5"); // fixed yearly interest rate in %
ecimal P = new BigDecimal(200000);
ecimal paymentYears = new BigDecimal(30);
onthly interest rate => 6.5 / 12 / 100 = 0.0054166667
ecimal r = interestRate.divide(new BigDecimal(12), 10, BigDecimal.ROUND_HALF_UP).divide(new
umerator
> 0.005416666 * 200000 = 1083.3333400000
ecimal numerator = r.multiply(P);
enominatorenominator
.add(new BigDecimal(1)); // => 1.0054166667
ecimal pow = new BigDecimal(30 * 12); // N = 30 * 12
> 1.005416666 ^ (-30 * 12) ===> 1 / 1.005416666 ^ (30 * 12)
ecimal one = BigDecimal.ONE;
ecimal r_pow = r.pow(pow.intValue()); // => 1.0054166667 ^ 360 = 6.99179805731691416804....
w = one.divide(r_pow, 10, BigDecimal.ROUND_HALF_UP); // => 1 / 6.991798.. = 0.1430247258
> 1 - 0.1430247258 = 0.8569752742
ecimal denominator = new BigDecimal(1);
minator = denominator.subtract(r_pow);
> 1083.3333400000 / 0.8569752742 = 1264.1360522464
ecimal c = numerator.divide(denominator, 10, BigDecimal.ROUND_HALF_UP);
.setScale(2, BigDecimal.ROUND_HALF_UP);
em.out.println("c = " + c);
Calculate fixed monthly payment for a fixed rate mortgage by Java
).divide(new BigDecimal(100), 10, BigDecimal.ROUND_HALF_UP);
// => 1.0054166667 ^ 360 = 6.99179805731691416804....
// => 1 / 6.991798.. = 0.1430247258
Line of code: 15
8. Complex example
Calculate fixed monthly payment for a fixed rate mortgage by Java
m interestRate = new Num(6.5); // fixed yearly interest rate in %
m P = new Num(200000);
m paymentYears = new Num(30);
monthly interest rate : r = 6.5 / 100 / 12
m r = Calculator.builder().openBracket().val(interestRate).div(100).closeBracket().div(12).calculate();
= 30 * 12 * -1
m N = Calculator.builder().val(paymentYears).mul(12).mul(-1).calculate();
= (r * P) / (1 / (1 + r)^N
ulator c = new Calculator()
= (r * P) / (1 / (1 + r)^N
ulator c = new Calculator()
.openBracket()
.val(r).mul(P)
.closeBracket() // numerator
.div() // ---------------
.openBracket() // denumerator
.val(1).sub().openBracket().val(1).add(r).closeBracket
.closeBracket();
m result = c.calculate().setScale(2);
em.out.println("c = " + result); Line
Calculate fixed monthly payment for a fixed rate mortgage by Java
().div(12).calculate();
closeBracket().pow(N)
Line of code: 8
9. Complex example
Calculate fixed monthly payment for a fixed rate mortgage by Java
m interestRate = new Num("A", 6.5);
m P = new Num("B", 200000);
m paymentYears = new Num("C", -30);
ulator c = Calculator.builder("((A / 100 / 12) * B) / (1 - ((1 + (A / 100 / 12)) ^ (C * 12)))",
m result = c.calculate();
em.out.println("c = " + result.setScale(2));
Line
Calculate fixed monthly payment for a fixed rate mortgage by Java
((1 + (A / 100 / 12)) ^ (C * 12)))", interestRate, P, paymentYears);
Line of code: 6
10. Feature: Show calculation
Num interestRate = new Num("A", 6.5);
Num P = new Num("B", 200000);
Num paymentYears = new Num("C", -30);
Calculator c = Calculator.builder("((A / 100 / 12) * B) / (1 - ((1 + (A / 100 / 12)) ^ (C * 12)))",
c.setScale(10);
Num result = c.calculate(true, false); // track calculation steps, track details
for(String step : c.getCalculationSteps())
System.out.println(step);
System.out.println("c = " + result.setScale(2));
Output:
6.5 / 100 = 0.065
0.065/ 12 = 0.0054166667
0.0054166667 * 200000
6.5 / 100 = 0.065
0.065/ 12 = 0.0054166667
1 + 0.0054166667
-30 * 12 = -360
1.0054166667 ^ -360
1 - 0.1430247258
1083.33334/ 0.8569752742
c = 1264.14
calculation steps
((1 + (A / 100 / 12)) ^ (C * 12)))", interestRate, P, paymentYears);
= 0.065
= 0.0054166667
* 200000 = 1083.33334
= 0.065
= 0.0054166667
+ 0.0054166667 = 1.0054166667
360 = 0.1430247258
= 0.8569752742
/ 0.8569752742 = 1264.1360522464
11. Feature: Modularity
Calculator calc = new Calculator();
calc.register(QuestionOperator.class); // register custom operator '?'
calc.register(SumFunction.class); // register custom function 'sum'
calc.expression("2 ? 2 + 5 - 1 + sum(1,2,3,4)");
@SingletonComponent@SingletonComponent
public class QuestionOperator implements Operator {
....
// module for ‘?’ operator
....
}
@SingletonComponent
public class SumFunction implements Function {
....
// module for function ‘sum’
....
}
// register custom operator '?'
register custom function 'sum'
implements Operator {
12. Feature: Default configuration
roundingMode=HALF_UP
scale=2
stripTrailingZeros=true
decimalSeparator.out='.'
decimalSeparator.in='.'
numconverter[0]=org.jdice.calc.test.NumTest$CustomObject > org.jdice.calc.test.NumTest$CustomObjectNumConverter
Configure default properties with 'jcalc.properties' file in class path
numconverter[0]=org.jdice.calc.test.NumTest$CustomObject > org.jdice.calc.test.NumTest$CustomObjectNumConverter
operator[0]=org.jdice.calc.test.CustomOperatorFunctionTest$QuestionOperator
function[0]=org.jdice.calc.test.CustomOperatorFunctionTest$SumFunction
configuration
org.jdice.calc.test.NumTest$CustomObjectNumConverter
' file in class path
org.jdice.calc.test.NumTest$CustomObjectNumConverter
org.jdice.calc.test.CustomOperatorFunctionTest$QuestionOperator
org.jdice.calc.test.CustomOperatorFunctionTest$SumFunction