Add interest per parcel with BigDecimal?

2

I am creating a system where I need to calculate the interest and add the installments of a financing. For this, I'm using BigDecimal and I'm not able to perform the math operation following the rendering formula. How to do this?

I'm trying like this:

private void calcular(){
        /**
         * formula
         * PMT = PV. i
         *          ----
         *          1 - (1 + i)^-n
         * 
         */
        BigDecimal total = new BigDecimal(0);
        BigDecimal pmt = new BigDecimal(0);
        BigDecimal valorVeiculo = ValorBigDecimal.getValor(txtParcela.getText()); 
        Integer parcela = Integer.parseInt(txtParcela.getText());
        BigDecimal entrada = valorEntrada();
        BigDecimal juros = ValorBigDecimal.getValor(txtJuros.getText()).divide(new BigDecimal(100));

        //valor do veiculo - valor entrada
        total = total.add(valorVeiculo).subtract(entrada);

        //calcula prestacao
        pmt = pmt.add(total).multiply(juros.divide(new BigDecimal(1).subtract(new BigDecimal(1).add(juros).pow(parcela))));
        pmt = pmt.setScale(2, RoundingMode.HALF_EVEN);
        System.out.println(pmt);


    }

Screen

    
asked by anonymous 03.09.2016 / 20:54

2 answers

3

Solved. I followed 2 formulas to arrive at the result the first formula PMT = PV * i / 1 - (1 + i)^-n and the second formula PMT = PV / (1 + i)^n - 1 / (1 + i)^n * i . With the first formula I could not make it work, so I was successful using the second formula that was as below.

private void calcular(){
        /**
         * formulas
         * F1 -> PMT = PV * i / 1 - (1 + i)^-n (nao funciona)       
         * F2 -> PMT = PV / (1 + i)^n - 1 / (1 + i)^n * i (funciona 100%)
         */
        BigDecimal total = new BigDecimal(0);
        BigDecimal diferenca = new BigDecimal(0);
        BigDecimal pv = ValorBigDecimal.getValor(txtValorVeiculo.getText());
        BigDecimal juros = ValorBigDecimal.getValor(txtJuros.getText()).divide(new BigDecimal(100));
        BigDecimal entrada = getValorEntrada();
        Integer parcelas = Integer.parseInt(txtParcela.getText());
        BigDecimal taxa = new BigDecimal(0);
        BigDecimal t1 = new BigDecimal(0);
        BigDecimal t2 = new BigDecimal(0);

        //calcula diferenca entre valor do veiculo e a entrada        
        diferenca = diferenca.add(pv).subtract(entrada);
        //(1 + i)^n - 1 
        t1 = BigDecimal.ONE.add(juros).pow(parcelas).subtract(BigDecimal.ONE);
        //(1 + i)^n * i
        t2 = BigDecimal.ONE.add(juros).pow(parcelas).multiply(juros);
        //(1 + i)^n - 1 / (1 + i)^n * i -> t1 / t2
        taxa = t1.divide(t2, 2, RoundingMode.HALF_UP);
        total = diferenca.divide(taxa, 2, RoundingMode.HALF_UP);

        System.out.println(t1);
        System.out.println(t2);
        System.out.println(taxa);
        System.out.println(total);        

    }
    
04.09.2016 / 02:25
2

Well, I did this class to solve your problem:

public final class PrecoComJuros {
    private final BigDecimal valorBase;
    private final BigDecimal valorParcelado; // pv
    private final BigDecimal entrada;
    private final int numeroParcelas;
    private final BigDecimal taxaJuros;
    private final BigDecimal valorParcela;
    private final BigDecimal valorTotal; // pmt
    private final BigDecimal valorJuros;

    public PrecoComJuros(BigDecimal valorBase, BigDecimal entrada, int numeroParcelas, BigDecimal taxaJuros) {
        if (numeroParcelas <= 0) throw new IllegalArgumentException();
        if (taxaJuros.compareTo(BigDecimal.ZERO) < 0) throw new IllegalArgumentException();
        this.valorBase = valorBase;
        this.entrada = entrada;
        this.numeroParcelas = numeroParcelas;
        this.taxaJuros = taxaJuros;
        BigDecimal juros = taxaJuros.divide(CEM); // i
        this.valorParcelado = valorBase.subtract(entrada);
        if (taxaJuros.compareTo(BigDecimal.ZERO) == 0) {
            this.valorParcela = valorParcelado.divide(BigDecimal.valueOf(numeroParcelas), 2, RoundingMode.HALF_EVEN);
        } else {
            BigDecimal potencia = juros.add(BigDecimal.ONE).pow(numeroParcelas);
            BigDecimal denominador = BigDecimal.ONE.subtract(BigDecimal.ONE.divide(potencia, 20, RoundingMode.HALF_EVEN));
            this.valorParcela = valorParcelado.multiply(juros).divide(denominador, 2, RoundingMode.HALF_EVEN);
        }
        this.valorJuros = valorParcela.multiply(BigDecimal.valueOf(numeroParcelas));
        this.valorTotal = entrada.add(valorJuros);
    }

    public BigDecimal getValorBase() {
        return valorBase;
    }

    public BigDecimal getValorParcelado() {
        return valorParcelado;
    }

    public BigDecimal getEntrada() {
        return entrada;
    }

    public int getNumeroParcelas() {
        return numeroParcelas;
    }

    public BigDecimal getTaxaJuros() {
        return taxaJuros;
    }

    public BigDecimal getValorParcela() {
        return valorParcela;
    }

    public BigDecimal getValorTotal() {
        return valorTotal;
    }

    public BigDecimal getValorJuros() {
        return valorJuros;
    }
}

Here's her test:

public static void main(String[] args) {
    System.out.println(Arrays.toString(" : : ".split(":")));
    PrecoComJuros p = new PrecoComJuros(BigDecimal.valueOf(30_000), BigDecimal.valueOf(10_000), 24, BigDecimal.valueOf(5));
    System.out.println("Valor da parcela: " + p.getValorParcela());
    System.out.println("Juros total: " + p.getValorJuros());
    System.out.println("Valor total: " + p.getValorTotal());
}

Some remarks about the implementation:

  • Passing a negative exponent to the pow method causes an exception. The solution to this is to note that a ^ (- b) = 1 / (a ^ b) http://mathurl.com/ju3n77z.png , and therefore we can eliminate the need to use a negative exponent.

  • There is special treatment in case the interest rate is zero. If there was no such treatment, a division by zero would occur.

  • Values with zero or negative numbers or with negative interest rates are rejected.

  • The parcel value is calculated with cents accuracy (2 digits after the comma). Intermediate calculations, however use up to 20 boxes after the comma.

04.09.2016 / 03:38