0

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?

4

3 回答 3

6

7/100/12 大约是 0.00583333333,而不是 0.005833。当您使用 %f 时,默认情况下您只会看到小数点后的 6 位数字。

于 2014-02-02T22:05:18.293 回答
4

BigDecimal bigResult = BigDecimal.valueOf(1.0 + monthlyInterestRate);

当您创建 BigDecimal 时,您会失去精度,因为1.0 + monthlyInterestRate会失去精度。BigDecimal为了获得更好的精度,为 1.0创建一个,然后使用该add()方法将其添加到另一个BigDecimal值为 0.005833。然后使用该BigDecimal pow()功能。

换句话说,BigDecimal从更简单的BigDecimalsnotintdouble类型构造。

于 2014-02-02T22:08:02.370 回答
1

差异是由于在硬编码结果计算中将monthlyInterestRate 的实际值0.005833333333333333599324266316443754476495087146759033203125 四舍五入为0.005833。为方便起见,我将程序修改为使用 System.out.println。我更改了monthlyInterestRate 的输出以准确打印它,然后在硬编码计算中使用该值。输出是:

monthlyInterestRate: 0.005833333333333333599324266316443754476495087146759033203125
numberOfPayments: 360

Hardcoded result:
(1 + 0.005833333333333333599324266316443754476495087146759033203125)^360 = 8.116497

Parameterized result:
(1 + 0.005833)^360 = 8.116497

BigDecimal result:
(1 + 0.005833)^360 = 8.116497

这是修改后的程序:

import java.math.BigDecimal;

public class Test {
    public static void main(String[] args) {
        double interestRatePercent = 7;
        int MONTHS_PER_YEAR = 12;
        int loanTermInYears = 30;
        double monthlyInterestRate = (interestRatePercent / 100)
                / MONTHS_PER_YEAR;
        int numberOfPayments = loanTermInYears * MONTHS_PER_YEAR;

        // System.out.println(String.format("monthlyInterestRate: %f",
        // monthlyInterestRate));
        System.out.println("monthlyInterestRate: "
                + new BigDecimal(monthlyInterestRate));
        System.out.println(String.format("numberOfPayments: %d",
                numberOfPayments));
        System.out.println("  ");

        System.out.println("Hardcoded result:");
        double hardcodedResult = Math
                .pow(1.0 + 0.005833333333333333599324266316443754476495087146759033203125,
                        numberOfPayments);
        System.out
                .println(String
                        .format("(1 + 0.005833333333333333599324266316443754476495087146759033203125)^360 = %f",
                                hardcodedResult));
        System.out.println("  ");

        System.out.println("Parameterized result:");
        double paramResult = Math.pow(1.0 + monthlyInterestRate,
                numberOfPayments);
        System.out.println(String.format("(1 + %f)^%d = %f",
                monthlyInterestRate, numberOfPayments, paramResult));
        System.out.println("  ");

        System.out.println("BigDecimal result:");
        BigDecimal bigResult = BigDecimal.valueOf(1.0 + monthlyInterestRate);
        bigResult = bigResult.pow(numberOfPayments);
        System.out.println(String.format("(1 + %f)^%d = %f",
                monthlyInterestRate, numberOfPayments, bigResult));
        System.out.println("  ");
        System.out.println("  ");
    }
}
于 2014-02-02T22:19:17.820 回答