I'm working on a mortgage calculation equation and I'm getting differing results from Math.pow() and I don't know why.
Here is the test setup:
double interestRatePercent = 7;
double monthlyInterestRate = (interestRatePercent / 100) / MONTHS_PER_YEAR;
int numberOfPayments = loanTermInYears * MONTHS_PER_YEAR;
Log.i(TAG, String.format("monthlyInterestRate: %f", monthlyInterestRate));
Log.i(TAG, String.format("numberOfPayments: %d", numberOfPayments));
Log.i(TAG, " ");
Log.i(TAG, "Hardcoded result:");
double hardcodedResult = Math.pow(1.0 + 0.005833, numberOfPayments);
Log.i(TAG, String.format("(1 + 0.005833)^360 = %f", hardcodedResult));
Log.i(TAG, " ");
Log.i(TAG, "Parameterized result:");
double paramResult = Math.pow(1.0 + monthlyInterestRate, numberOfPayments);
Log.i(TAG, String.format("(1 + %f)^%d = %f", monthlyInterestRate, numberOfPayments, paramResult));
Log.i(TAG, " ");
Log.i(TAG, "BigDecimal result:");
BigDecimal bigResult = BigDecimal.valueOf(1.0 + monthlyInterestRate);
bigResult = bigResult.pow(numberOfPayments);
Log.i(TAG, String.format("(1 + %f)^%d = %f", monthlyInterestRate, numberOfPayments, bigResult));
Log.i(TAG, " ");
Log.i(TAG, " ");
Here is the test results:
monthlyInterestRate: 0.005833
numberOfPayments: 360
Hardcoded result:
(1 + 0.005833)^360 = 8.115529
Parameterized result:
(1 + 0.005833)^360 = 8.116497
BigDecimal result:
(1 + 0.005833)^360 = 8.116497
Only the hard-coded result is correct. Both the Math.pow and BigDecimal.pow results are bad.
Any ideas?
BigDecimal bigResult = BigDecimal.valueOf(1.0 + monthlyInterestRate);
When you are creating your BigDecimal, you'll get loss of precision, since 1.0 + monthlyInterestRate
will lose precision. To get better precision, create a BigDecimal
for 1.0, then use the add()
method to add it to another BigDecimal
with the value 0.005833. Then use the BigDecimal
pow()
function.
In other words, construct the BigDecimal
from simpler BigDecimals
not int
or double
types.