Expression does not return the desired result when the data is captured by the input

Asked

Viewed 82 times

5

I made an expression to calculate compound interest with monthly contribution, based On that website The expression went like this:

function jurosCompostosComAporte(p,m,i,n){
  let valorFuturo,
      valorPresente=p,
      mensalidade=m,
      periodo=n,
      taxa=i;
  
      valorFuturo =  valorPresente * Math.pow( 1 + taxa , periodo ) +
      mensalidade * ((Math.pow( 1 + taxa , periodo ) - 1) / taxa);

      return valorFuturo.toFixed(2);

}

console.log(jurosCompostosComAporte(100,10,0.030,12)); 
//Valor inicial 100 com 10 depositados mensalmente: rendimento de 3% durante 12 meses.

Everything works as expected, even when entering the values with input's via DOM.

When entering the fee for a input number, it returns results far greater than expected, such as 1.969946535161522e+25 (I tested the same rate of 0.030 = 3% in input and inserting via code, returned in the code 36.46).

I would like to know why this happens, because when I enter the fee without taking the input, everything happens without errors.

Here the function I pull the rate of input:

function calculateResults(valorInicialID, valorMensalID ,taxaID,tempoId){
    var valorInicial = document.getElementById(valorInicialID).value;
    var valorMensal = document.getElementById(valorMensalID).value;
    var taxaCustomizada = document.getElementById(taxaID).value;
    var tempo = document.getElementById(tempoId).value;

    document.getElementById('poupanca').innerHTML = jurosCompostosComAporte(valorInicial,valorMensal,0.0040,tempo);
    document.getElementById('rendafixa').innerHTML = jurosCompostosComAporte(valorInicial,valorMensal,0.0050,tempo);
    document.getElementById('tesourodireto').innerHTML = jurosCompostosComAporte(valorInicial,valorMensal,0.0070,tempo);
    document.getElementById('carteiraalunos').innerHTML = jurosCompostosComAporte(valorInicial,valorMensal,0.030,tempo);
    document.getElementById('seujuroscustomizado').innerHTML = jurosCompostosComAporte(valorInicial,valorMensal,taxaCustomizada,tempo);
 Valor inicial: <input type="number" id="valorinicial"><br>
    Aporte mensal: <input type="number" id="valormensal"><br>
    Taxa: <input type="number" id="taxacustomizada"><br>
    Tempo: <input type="number" id="tempo"> 
    <select  id="seletorTempo">
        <option value="0">Meses</option>
        <option value="1">Anos</option>
    </select><br>
    <div id="chart-container"></div>

    <a href="#" onclick="calculateResults('valorinicial','valormensal','taxacustomizada', 'tempo')">Ativar</a>

    <p id="poupanca"></p>
    <p id="rendafixa"></p>
    <p id="tesourodireto"></p>
    <p id="carteiraalunos"></p>
    <p id="seujuroscustomizado"></p>

1 answer

7


This happens because the value of an element is always a string. So when you pass the document.getElementById(...).value, the function jurosCompostosComAporte is receiving a string.

And when you pass the rate as a string, adding 1 the result is not quite what you expect:

console.log(1 + 0.03); // 1.03
console.log(1 + '0.03'); // 10.03

Note that in the second case a concatenation was made with the string, resulting in 10.03. Next, Math.pow will convert this to number, and the result will be 10.03 - not 1.03 - taken over the period.

The solution is to convert the values to numbers. As the initial and monthly values, as well as the rate, can have decimal places, use parseFloat to convert the string to a number. Already for the period, I understand that can only be integer values, so use parseInt (unless you want to calculate 2.7 months, then use parseFloat).

In addition, the function jurosCompostosComAporte could already receive the variables with the correct names (and also more significant), and exponentiation could be done only once:

function jurosCompostosComAporte(valorPresente, mensalidade, taxa, periodo){
    let t = Math.pow(1 + taxa, periodo); // calcula uma vez só
    let valorFuturo = valorPresente * t + mensalidade * ((t - 1) / taxa);

    return valorFuturo.toFixed(2);
}

function calculateResults(valorInicialID, valorMensalID ,taxaID,tempoId){
    let valorInicial = parseFloat(document.getElementById(valorInicialID).value);
    let valorMensal = parseFloat(document.getElementById(valorMensalID).value);
    let taxaCustomizada = parseFloat(document.getElementById(taxaID).value);
    let tempo = parseInt(document.getElementById(tempoId).value);

    document.getElementById('poupanca').innerHTML = jurosCompostosComAporte(valorInicial,valorMensal,0.0040,tempo);
    document.getElementById('rendafixa').innerHTML = jurosCompostosComAporte(valorInicial,valorMensal,0.0050,tempo);
    document.getElementById('tesourodireto').innerHTML = jurosCompostosComAporte(valorInicial,valorMensal,0.0070,tempo);
    document.getElementById('carteiraalunos').innerHTML = jurosCompostosComAporte(valorInicial,valorMensal,0.030,tempo);
    document.getElementById('seujuroscustomizado').innerHTML = jurosCompostosComAporte(valorInicial,valorMensal,taxaCustomizada,tempo);
}
 Valor inicial: <input type="number" id="valorinicial"><br>
    Aporte mensal: <input type="number" id="valormensal"><br>
    Taxa: <input type="number" id="taxacustomizada"><br>
    Tempo: <input type="number" id="tempo"> 
    <select  id="seletorTempo">
        <option value="0">Meses</option>
        <option value="1">Anos</option>
    </select><br>
    <div id="chart-container"></div>

    <a href="#" onclick="calculateResults('valorinicial','valormensal','taxacustomizada', 'tempo')">Ativar</a>

    <p id="poupanca"></p>
    <p id="rendafixa"></p>
    <p id="tesourodireto"></p>
    <p id="carteiraalunos"></p>
    <p id="seujuroscustomizado"></p>


Recalling further that toFixed can round up the value, but there are other ways to round up the number or not:

function arredonda(valor) {
    return Math.round(valor * 100) / 100;
}

function naoArredonda(valor) {
    return Math.floor(valor * 100) / 100;
}

[1.478, 1.472].forEach(n =>
  console.log(`${n} => ${arredonda(n)}, ${naoArredonda(n)}, ${n.toFixed(2)}`));

  • Thank you very much! I thought the value was already in number, because the type of the field in HTML was number, and when debugging in the console. The numbers appeared without quotation marks (which usually appear in strings). Now everything is OK. Thanks also for the syntax touches and code optimizations!

  • @Lucas If the answer solved your problem, you can accept it, see here how and why to do it. It is not mandatory, but it is a good practice of the site, to indicate to future visitors that it solved the problem. And when I get 15 points, you can also vote in all the answers you found useful.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.