Rafael
Rafael

Reputation: 1487

JavaScript calculating wrong percentage in two inputs

I have the following inputs:

cost, where I type in a currency value, like 6,23, profit, where I type in a percentage value like 29,21 and value where the sum of the both values is show.

JavaScript does the math and returns me in value the value from cost + the currency value of the percentage typed in profit, in which case the result is 8,05 (6,23 + 29,21%).

But if try to do the same, but informing the value instead of profit, as the same 8,05, so JavaScript would return me the profit of 29,21, but it returns me 36,44.

Does anyone know what it can be?

Here is my code:

$(document).ready(function () {
    $(".valor").on("input", function () {
        // Margem
        var valor = $(this).val();
        var valorCorrigido = parseFloat(adicionarPontos(valor));
           
        var valorFloat = parseFloat(valorCorrigido) || 0.0;

        // Custo  
        var valorCusto = $('#custo').val();
        var valorCustoCorrigido = parseFloat(removerPontos(valorCusto));
        var valorCustoFloat = parseFloat(valorCustoCorrigido) || 0.0;

        // Calculo
        var calculo = (parseFloat(valorFloat) - parseFloat(valorCustoFloat)) / parseFloat(valorCustoFloat) * 100;
        var inputMargem = $(this).attr("margem");

        $("#" + inputMargem).val(calculo.toFixed(2)).trigger('blur');
    });
    // Faz o calculo do valor com base na margem
    $(".margem").on("input", function () {
        // Margem
        var valorMargem = $(this).val();  
        var valorMargemCorrigido = parseFloat(adicionarPontos(valorMargem));
        var valorMargemFloat = parseFloat(valorMargemCorrigido) || 0.0; 

        // Custo
        var valorCusto = $('#custo').val();
        var valorCustoCorrigido = parseFloat(removerPontos(valorCusto));
        var valorCustoFloat = parseFloat(valorCustoCorrigido) || 0.0; 

        // Cálculo
        var calculo = (parseFloat(valorCustoFloat) * parseFloat(valorMargemFloat) / 100) + parseFloat(valorCustoFloat);
        var inputValor = $(this).attr("valor");

        var resultadoMonetario = calculo.toFixed(2).toString();
        resultadoMonetario = resultadoMonetario.replace(".", ",");

        $("#" + inputValor).val(resultadoMonetario).trigger('blur');
    });

    function removerPontos(valor){
        valor = valor.replace(".","");
        valor = valor.replace(",",".");
        return valor;           
    }
    
    function adicionarPontos(valor){
       if(valor.length == 1){
           return valor;
       }
       else{
       if(valor.length == 2){
           return valor;
       }
       else{

       // The problem was here

       valor = valor.replace(",","");
       var inteiro = valor.substring(0,valor.length - 2);
       var decimal = valor.substr(2);
       return inteiro + "." + decimal;
       }
       }
    }
});

$('input').mask('00.000.000,00', {
    reverse: true
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.mask/1.13.4/jquery.mask.js"></script>


Custo:
<input type='text' id='custo' class='custo valores' name='custo'>
<br>
<br> Valor:
<input type='text' id='valor1' class='valor valores' name='valor1' margem='margem1'> Margem:
<input type='text' id='margem1' class='margem valores' name='margem1' valor="valor1">

<br> Valor:
<input type='text' id='valor2' class='valor valores' name='valor2' margem='margem2'> Margem:
<input type='text' id='margem2' class='margem valores' name='margem2' valor="valor2">

Upvotes: 0

Views: 474

Answers (3)

Rafael
Rafael

Reputation: 1487

So seems that the problem was in this part of the code:

valor = valor.replace(",","");
var inteiro = valor.substring(0,valor.length - 2); 
var decimal = valor.substr(2);
return inteiro + "." + decimal;

After changing it to this worked fine:

 var inteiro = valor.substring(0,valor.length - 2);
 var decimal = valor.substring(valor.length - 2, valor.length);

Upvotes: 0

Yanick Rochon
Yanick Rochon

Reputation: 53576

If your total profit equation is total = cost + (cost * profit).

Then your profit % equation should be profit = (total - cost) / cost.

Here are two functions that provide you with what you need. You might be interested to use them instead of calculating in line like how you do in your question.

function getProfitTotal(cost, profit) {
  cost = parseFloat(cost, 10);
  profit = parseFloat(profit, 10) / 100;

  return cost + (cost * profit);
}

function getProfitMargin(cost, total) {
  cost = parseFloat(cost, 10);
  total = parseFloat(total, 10);

  return (total - cost) / cost * 100;
}

Thus getProfitMargin(6.23, getProfitTotal(6.23, 21.23) ); will output 21.23. Just use .toFixed(2) before setting the value in your text field.

On a side note, you should only reset your field's value if the value is NaN. As of now, I am personally unable to write decimals in the example you provided because of this.

Also, all numbers have to be dot-separated. Just parse and format your numbers with a globalization library, as your current functions are not working correctly as described earlier.

Upvotes: 0

twernt
twernt

Reputation: 20601

The calculations appear to be incorrect because decimal separators in JavaScript are not localized.

6,23 * 29,21 // 21

6.23 * 29.21 // 181.97830000000002

parseFloat(6,23); // 6

parseFloat(6.23); // 6.23

You can use Number.prototype.toLocaleString() or a currency formatting plugin to format the values for display, but your custo, valor, and margem values should be formatted with a . decimal separator when you do your calculations.

Upvotes: 1

Related Questions