Cálculo VPL e TIR
Cálculo VPL e TIR (método Bisseção)
by Alexandre Gomiero de Oliveira
HTML
<form id="calculos">
<div class="fundo cor_azul">
Montante em cada período:
<input id="mont" type="text" size="52" placeholder="ex: -30000.02, 10000.5, 5000, ..." value="" />
<ul style="font-size: 11pt">
<li>Valores separados por vírgulas: <code>-3000,350.20, ...</code></li>
<li>não pode haver inversão de sinal após o primeiro valor</li>
</ul>
</div><br />
<div class="fundo cor_azul">
Taxa de desconto: <input id="desc" type="text" size="12" placeholder="ex: 0.05 para 5%" value="" /><br />
</div><br />
<input id="calc" type="button" name="name" value="calcular" onclick="calcula();">
<input id="reset" type="reset" name="name" value="limpar" />
<br /><br />
<div class="fundo cor_verde">
<table>
<tr>
<td>VPL ($):</td><td><input id="result_vpl" type="text" class="alinhamento" size="8" align="right" readonly="true" /></td>
</tr><tr>
<td>TIR (%):</td><td><input id="result_tir" type="text" class="alinhamento" size="8" form="calculos" readonly="true" /></td>
</tr>
</table>
</div>
</form>
CSS
body {
font-family: sans-serif;
}
.fundo {
border-radius: 5px;
padding: 15px;
width: 400px;
}
.cor_azul {
background: rgb(230, 230, 250);
}
.cor_verde {
background: rgb(220, 235, 220);
}
.alinhamento {
text-align: right;
}
code {
background-color: lightgray;font-size: 10pt;
}
JavaScript
"use strict";
/*
* Calcula o Valor Presente Líquido para
* um período constante sem inversão de sinal
*
* @taxa => taxa de desconto
* @montantes => vetor com os valores com os recebimentos ou pagamentos
* -100,30,30,10,10,10,10
*/
function vpl(taxa, montantes)
{
var ret = montantes[0];
for (var i=1; i<montantes.length; i++)
ret += montantes[i] / Math.pow( (1.0 + taxa), i);
return ret;
}
/*
* Calcula a Taxa Interna de Retorno
*
* @montantes => vetor com os valores
*/
function tir(montantes)
{
var ret = -1000000000.0;
var juros_inicial = -1.0;
var juros_medio = 0.0;
var juros_final = 1.0;
var vpl_inicial = 0.0;
var vpl_final = 0.0;
var vf = 0.0;
var erro = 1e-5;
for (var i=0; i<100; i++) {
vpl_inicial = vpl(juros_inicial, montantes);
vpl_final = vpl(juros_final, montantes);
if (sinal(vpl_inicial) != sinal(vpl_final))
break;
juros_inicial -= 1.0;
juros_final += 1.0;
};
var count = 0;
for (;;) {
// Busca por Bisseção
var juros_medio = (juros_inicial + juros_final) / 2.0;
var vpl_medio = vpl(juros_medio, montantes)
if (Math.abs(vpl_medio) <= erro) {
// Resultado foi encontrado
return juros_medio*100.0;
};
if (sinal(vpl_inicial) == sinal(vpl_medio)) {
juros_inicial = juros_medio;
vpl_inicial = vpl(juros_medio, montantes);
} else {
juros_final = juros_medio;
vpl_final = vpl(juros_medio, montantes);
};
if (++count > 10000)
throw "looping inválido";
};
return ret;
};
function sinal(x) {
return x < 0.0 ? -1 : 1;
}
function calcula()
{
var taxa_campo = document.getElementById('desc');
var montantes_campo = document.getElementById('mont');
var result_vpl_campo = document.getElementById('result_vpl');
var result_tir_campo = document.getElementById('result_tir');
var taxa...