0

我想创建一个摊销计算器,以从N个贷方获取 36 个月贷款的报价,其中每个贷方都有不同的利率。目标是提供尽可能的利率,并提供每月还款额和总还款额。我的代码结果很接近但不准确

我正在使用公式公式

计算i(利率)为total amount lended / requested amount,其中借出的总金额是每个贷方借出的钱乘以贷方的利率。

    BigDecimal requestedAmountP = new BigDecimal("" + requestedAmount);
    BigDecimal minLendersRate = calculateRate(requestedAmount, lenders);

    // https://en.wikipedia.org/wiki/Mortgage_calculator#Monthly_payment_formula
    // r*P/(1 - (1+r)^(-N))         if r != 0
    // P/N                          if r == 0
    BigDecimal monthlyRepayment;
    if (minLendersRate.compareTo(BigDecimal.ZERO) == 0) {
        monthlyRepayment = requestedAmountP.divide(DURATION_MONTHS, MathContext.DECIMAL128);
    } else {
        BigDecimal r = calculateEffectiveInterestInMonths(minLendersRate);
        BigDecimal tmp = r.add(BigDecimal.ONE).pow(-DURATION_MONTHS.intValue(), MathContext.DECIMAL128);
        BigDecimal dividend = BigDecimal.ONE.subtract(tmp);
        monthlyRepayment = r.multiply(requestedAmountP).divide(dividend, MathContext.DECIMAL128);
    }
    BigDecimal totalRepayment = monthlyRepayment.multiply(DURATION_MONTHS);

计算费率:

private BigDecimal calculateRate(double requestedAmount, List<Lender> lenders) {
    List<Lender> sortedLenders = lenders.stream().sorted(Comparator.comparing(Lender::getRate)).collect(toList());
    List<BigDecimal> moneyLended = moneyLended(requestedAmount, sortedLenders);

    BigDecimal totalMoneyLended = IntStream.range(0, moneyLended.size())
            .mapToObj(index -> moneyLended.get(index).multiply(sortedLenders.get(index).getRate()))
            .reduce(BigDecimal.ZERO, BigDecimal::add);

    return totalMoneyLended.divide(new BigDecimal("" + requestedAmount), MathContext.DECIMAL128);
}

private List<BigDecimal> moneyLended(double requestedAmount, List<Lender> sortedLenders) {
    List<BigDecimal> moneyLended = new ArrayList<>(sortedLenders.size());

    int i = 0;
    Double remaining = requestedAmount;
    while (remaining > 0) {
        if (remaining - sortedLenders.get(i).getAvailable().doubleValue() >= 0) {
            remaining = remaining - sortedLenders.get(i).getAvailable().doubleValue();

        } else {
            remaining = 0d;
        }
        moneyLended.add(sortedLenders.get(i).getAvailable());
        i++;
    }
    return moneyLended;
}

以月计算有效利息

private BigDecimal calculateEffectiveInterestInMonths(BigDecimal nominalInterest) {
    // Formula: ((1+nominalInterest)^(1/12))-1
    BigDecimal exp = BigDecimal.ONE.divide(new BigDecimal("12"), MathContext.DECIMAL128);
    return BigDecimalMath.pow(BigDecimal.ONE.add(nominalInterest), exp, MathContext.DECIMAL128)
            .subtract(BigDecimal.ONE);
}

十进制运算似乎有问题,但我不知道在哪里。

4

0 回答 0