Calculate integral trapezoid mode

5

I need to calculate integral with the trapezoid method. I believe the error can be in for . I had tested them step by step and it worked.

    function integratrapezio(){         
    var elmbasea = document.getElementById("valoresdex").value;
    var elemb = document.getElementById("valoresdey").value;
    var elemquant = document.getElementById("valoresden").value;
    var elemfuncao = document.getElementById("valordafuncao").value;

    var k = (elmbasea-elemb)/elemquant;

    var n = +elemquant+1;   
    var elemk = +k/2;

    var f = "x+2";

    var cont = 0;

    for (j=1;j<n; j++){

        var i=+j-1;
                if ((i == 0)){c=1;}else{c=2;}
                var x=+elmbasea+i*+k;   

                var funcao = eval(elemfuncao);

                var calculodafuncao=cont+c*funcao;
                var cont = calculodafuncao;

        alert(calculodafuncao);             

    }



    var total=+elemk*+calculodafuncao;

    /*qualcular a função f = (x)       https://www1.univap.br/spilling/CN/CN_Capt6.pdf*/                
    if(document.getElementById('resultFunc').style.visibility = 'Visible'){document.getElementById('resultFunc').style.visibility = 'hidden';}

    if(document.getElementById('resultFunc').style.visibility = 'hidden'){document.getElementById('resultFunc').style.visibility = 'visible';}

    document.getElementById('resultFunc').innerHTML = total;

}
    
asked by anonymous 04.11.2017 / 00:08

1 answer

6

Particularly I found it very strange what you did to calculate the integral in the trapeze mode. You do not have too many secrets when doing the integral with this method. The only questionable question is whether you define the size of the trapezoids or how many trapezoids divide the range. The following is an example of the size of each trapezoid:

function trapezio(lbda, ini, fim, delta) {
  let integral = 0.0;
  let last_lbda = lbda(ini);
  for (let i = ini + delta; i <= fim; i += delta) {
    let now_lbda = lbda(i);
    integral += delta*(now_lbda+last_lbda)/2;
    last_lbda = now_lbda;
  }
  return integral;
}

function info_trapezio_quadrado(ini, fim, delta) {
  let result = trapezio((i) => i*i, ini, fim, delta);
  console.log("função quadrada, de " + ini + " a " + fim +", delta = " + delta);
  console.log(">integral = " + result);
}

info_trapezio_quadrado(0, 2, 1);
info_trapezio_quadrado(0, 2, 0.5);
info_trapezio_quadrado(0, 2, 0.1);
info_trapezio_quadrado(0, 2, 0.01);
info_trapezio_quadrado(0, 2, 0.001);

Explaining the code:

  • arguments are any function of the real in the real lbda , the [ini, fim) interval, and the base size of the trapezoids delta
  • Calculating the area of a rectangle trapezoid is base * (altura1 + altura2)/2
  • integral is the sum of the area of all trapezoids, starting with ini and ending with fim

A version that does less operations, but less readable, is:

function trapezio_menos_operacoes(lbda, ini, fim, delta) {
  let lbda_ini = lbda(ini);
  let somas = lbda_ini;
  let last_lbda = lbda_ini;
  for (let i = ini + delta; i <= fim; i += delta) {
    last_lbda = lbda(i)
    somas += last_lbda;
  }
  let integral = delta*(somas - (lbda_ini + last_lbda)/2.0);
  return integral;
}

In this version, I'm making sure that each height of the trapezoids is taken into account twice in the original version (except the first and last). For example, for the square function with delta = 0.5 (integrating from 0 to 2):

iteração | i    | f(i) | área do trapézio              | área acumulada
---------+------+------+-------------------------------+----------------
0        | 0    | 0    | 0                             | 0
1        | 0.50 | 0.25 | 0.5*(0.00 + 0.25)/2 = 0.0625  | 0.0625
2        | 1.00 | 1.00 | 0.5*(0.25 + 1.00)/2 = 0.3125  | 0.3750
3        | 1.50 | 2.25 | 0.5*(1.00 + 2.25)/2 = 0.8125  | 1.1875
4        | 2.00 | 4.00 | 0.5*(2.25 + 4.00)/2 = 1.5625  | 2.7500

Did you notice how% of f(0.5) was repeated in two moments? In the trapezoid area of iteration 1 and in iteration 2? And that the same happened to f(1.0) (iterations 2 and 3) and f(1.5) (iterations 3 and 4)? If I did the sums in the hand it would be something like this:

delta*(f(0.0) + f(0.5))/2 + [primeiro trapézio]
delta*(f(0.5) + f(1.0))/2 + [segundo trapézio]
delta*(f(1.0) + f(1.5))/2 + [terceiro trapézio]
delta*(f(1.5) + f(2.0))/2   [quarto trapézio]
-------------------------
delta/2 * (
  f(0.0) +
  f(0.5) + f(0.5) +
  f(1.0) + f(1.0) +
  f(1.5) + f(1.5) +
  f(2.0)
)

The rest were mathematical tricks to minimize the amount of operations.

Apparently, you want to get the formula somewhere, right? Well, we can get the input, the variable being x :

function faz_leitura(form) {
  let ini = Number(document.getElementById("ini").value);
  let fim = Number(document.getElementById("fim").value);
  let delta = Number(document.getElementById("delta").value);
  let equacao = document.getElementById("equacao").value;
  
  let pre_lambda = "(x) => " + equacao;
  let lbda = eval(pre_lambda);
  
  let result = trapezio_menos_operacoes(lbda, ini, fim, delta);
  document.write("<div>Integral de " + ini + " até " + fim + " (delta " + delta + "), para a função " + pre_lambda + ": " + result + "</div>");
}

function trapezio_menos_operacoes(lbda, ini, fim, delta) {
  let lbda_ini = lbda(ini);
  let somas = lbda_ini;
  let last_lbda = lbda_ini;
  for (let i = ini + delta; i <= fim; i += delta) {
    last_lbda = lbda(i)
    somas += last_lbda;
  }
  let integral = delta*(somas - (lbda_ini + last_lbda)/2.0);
  return integral;
}
<form onsubmit="faz_leitura(this); return false;">
<div>
  <input required type="text" id="equacao"/>
  <label>equação (use 'x' minúsculo para a variável)</label>
</div>
<div>
  <input required type="text" id="ini"/>
  <label>ini</label>
</div>
<div>
  <input required type="text" id="fim"/>
  <label>fim (deve ser maior que ini)</label>
</div>
<div>
  <input required type="text" id="delta">
  <label>delta (deve ser positivo)</label>
</div>
<button type="submit">Integral</button>
</form>

Did you notice that here I separated the concern of each function? It has the function that deals with the submission of the form, filling in the variables ( faz_leitura ) and the function that actually does the integral calculation in the trajectory strategy ( trapezio_menos_operacoes ). My separation was not good, I'm not the most experienced in Javascript + HTML, but it already separates business logic from the interface.

  

Looking at another answer , I come across the possible malicious use of eval() . So, avoid eval() , it's easier. I will edit this question to use new Function() , but now I am unable to test.

References:

Special thanks to the following users for helping me come up with the answer:   @Anderson Carlos Woss , @Victor Stafusa , @rray , @ pss1support

Observations on the differences between the two sums

On the two versions of the integration function, they are mathematically the same, considering arithmetic of real numbers and rational numbers. However, floating-point numbers follow other rules.

When you make a floating-point sum, you may lose precision. This is natural and sometimes even desirable. I'll go into more of this in one of the points of this answer .

The approach of not multiplying by the base of the trapezoid causes the numbers to be larger, since in the ideal this value should approach zero. So, possibly the value of the function may be insignificant compared to the cumulative total.

Another point to draw attention to is that if the value of lbda(x) is decreasing (even if the decay is getting smaller) as x approaches the final limit, the sum value will not change. This would only be postponed if the base value were multiplied.

One possible measure to avoid this would be to accumulate the numbers as long as they are totally significant in relation to the sum. When there is detection that the summed number will have part of the precision missed, it should start a new summation is so on. In the end, one should sort from the smallest to the largest and add up in that order. This would be one of the ways to ensure the accuracy of calculations using floating point as much as possible.

    
28.02.2018 / 05:22