Cómo calcular PI con la fórmula de Leibniz

En esta ocasión les enseñaré una forma de calcular PI desde la teoría, el pseudocódigo y el código en algunos lenguajes populares.

Para ello usaremos la fórmula de Leibniz, que si bien no es la más eficiente si es bastante fácil de implementar.

Fundamentos teóricos para calcular el número PI

Esta fórmula fue propuesta por Gottfried Leibniz y mediante una secuencia simple nos permite calcular el número PI.

La serie en cuestión es la siguiente:

\[1-\frac13+\frac15-\frac17+\frac19-…=\frac\pi4\]

Para hacer la serie más simple, usaremos la notación de sumatoria para obtener la ecuación:

\[\sum_{n=0}^\infty\frac{(-1)^n}{2n+1}=\frac\pi4\]

Finalmente despejamos para obtener el valor de PI.

\[\pi=4\cdot\sum_{n=0}^\infty\frac{(-1)^n}{2n+1}\]

Dicha ecuación será fácilmente portable a pseudocódigo convirtiendo la sumatoria en un ciclo de tipo “para cada”.

Pseudocódigo

El pseudocódigo queda de la siguiente manera:

LEE limite
pi<-0
PARA n<-0 HASTA limite PASO 1
 pi<-pi+(-1^n/(2n+1))
REGRESA pi*4

Es importante notar que si bien esta no es la única forma de hacerlo, por lo general las definiciones matemáticas se interpretan más fácilmente mediante el paradigma de la programación imperativa.

Código de práctica

Basados en ese pseudocódigo, mostraremos la implementación en distintos lenguajes tratando de aproximarnos con un error al valor ya aceptado de PI que se halla en las librerías de los lenguajes.

Estos códigos fueron probados en el sitio Codewars y son de mi total autoría.

Todos los códigos generarán una salida similar a la sigiente

3.141593-0.000000->
3.141593>0.1000000
->piAprox=4.000000 
3.141593-4.000000: 0.858407>0.100000
 1->piAprox=2.666667 
3.141593-2.666667: 0.474926>0.100000
 2->piAprox=3.466667 
3.141593-3.466667: 0.325074>0.100000
 3->piAprox=2.895238 
3.141593-2.895238: 0.246355>0.100000
 4->piAprox=3.339683 
3.141593-3.339683: 0.198090>0.100000
 5->piAprox=2.976046 
3.141593-2.976046: 0.165546>0.100000
 6->piAprox=3.283738 
3.141593-3.283738: 0.142146>0.100000
 7->piAprox=3.017072 
3.141593-3.017072: 0.124521>0.100000
 8->piAprox=3.252366 
3.141593-3.252366: 0.110773>0.100000
 9->piAprox=3.041840 
3.141593-3.041840: 0.099753>0.100000

Cabe mencionar que para acelerar el tiempo de ejecución lo más recomendable es comentar las impresiones ya que forman parte del mismo proceso.

Indicaciones

El objetivo del ejercicio es tratar de mostrar cuán difícil puede ser calcular decimales de un número irracional con cierta precisión. Hemos elegido obtener unos pocos decimales del número pi utilizando la siguiente serie infinita (Leibniz 1646-1716):

\[\frac\pi4=1-\frac13+\frac15-\frac17+…\]

lo que nos da una aproximación de PI / 4.

Para tener una medida de la dificultad contaremos cuántas iteraciones se necesitan para calcular PI con una precisión dada.

Hay varias maneras de determinar la precisión del cálculo, pero para mantener las cosas fáciles que se calcula dentro de un rango epsilon para la constante Math :: PI correspondiente en el lenguaje elegido.

En otras palabras, pararemos el proceso iterativo cuando el valor absoluto de la diferencia entre nuestro cálculo y la constante Math :: PI sea menor que epsilon.

Su función> iter_pi(epsilon) debe regresar un arreglo :
[numberOfIterations, approximationOfPi]

Donde la aproximación de PI tiene 10 decimales

En Haskell puede utilizar la función “trunc10Dble”, en Clojure puede utilizar la función “round” y en OCaml la función “rnd10”. Con el fin de evitar discusiones sobre el resultado.

Ejemplos:

Su función calcula 1000 iteraciones y 3.140592653839794 pero devuelve:
IterPi (0.001) -> [1000, 3.1405926538]

Desafortunadamente, esta serie converge demasiado lentamente para ser útil, ya que toma más de 300 términos para obtener una precisión de 2 decimales. Para obtener 100 lugares decimales de PI. ¡Se calculó que se necesitaría utilizar por lo menos 10 ^ 50 términos de esta expansión!

Más acerca de PI: http://www.geom.uiuc.edu/~huberty/math5337/groupe/expresspi.html.

Calcular pi en Javascript

Algunos conocimientos que pudiera necesitar para implementarlo en este lenguaje son:

  1. String templates: todo lo que esté entre los símbolos `` se ejecuta evaluando todo lo que se halle entre los símbolos ${} y convirtiendo el resultado a cadena
  2. Uso del operador comma que en este caso evalúa y llena un arreglo con los valores

El objetivo del kata es tratar de mostrar cuán difícil puede ser calcular decimales de un número irracional con cierta precisión.

function iterPi(epsilon) {
  var n=0;
  var piAprox=0;
  console.log(`${Math.PI}-${4*piAprox}->${Math.PI-piAprox}>${epsilon}`)
  while( Math.abs(Math.PI-4*piAprox) > epsilon ){
    piAprox+=(Math.pow(-1,n)) / (2*n+1);
    console.log(`${n}->piAprox=${4*piAprox}`);
    n++;
    console.log(`${Math.PI}-${4*piAprox}:\\n${Math.PI-4*piAprox}>${epsilon}`)
  }
  return [n,Number((4*piAprox).toFixed(10))];
}

Calcular pi en CoffeeScript

Algunos conocimientos que pudiera necesitar para implementarlo en este lenguaje son:

  1. String templates: todo lo que esté entre los símbolos "" se ejecuta evaluando todo lo que se halle entre los símbolos #{} y convirtiendo el resultado a cadena
  2. Uso del operador comma que en este caso evalua y llena un arreglo con los valores aunque no se ponga explícitamente
iterPi = (epsilon) ->
  n = 0
  piAprox = 0
  console.log "#{Math.PI}-#{4*piAprox}->#{Math.PI-4*piAprox}>#{epsilon}"
  while Math.abs(Math.PI - (4 * piAprox)) > epsilon
    piAprox += (-1) ** n / (2 * n + 1)
    console.log "#{n}->piAprox=#{4*piAprox}"
    n++
    console.log "#{Math.PI}-#{4*piAprox}:\\n#{Math.PI-4*piAprox}>#{epsilon}"
  [
    n
    Number((4 * piAprox).toFixed(10))
  ]

Calcular pi en Java

Algunos conocimientos que pudiera necesitar para implementarlo en este lenguaje son:

  1. Varargs: el mecanismo de procesar un numero variable parámetros
  2. Formateo de cadenas
public class PiApprox {
    public static String iterPi2String(Double epsilon) {
        int n = 0;
      double piAprox=0;
      System.out.printf("%f-%f->%f>%f\\n",Math.PI,4*piAprox,Math.PI-4*piAprox,epsilon);
      while( Math.abs(Math.PI-4*piAprox) > epsilon ){
        piAprox+=(Math.pow(-1,n)) / (2*n+1);
        System.out.printf("%d->piAprox=%f\\n",n,4*piAprox);
        n++;
        System.out.printf("%f-%f:\\n%f>%f\\n",Math.PI,4*piAprox,Math.abs(Math.PI-4*piAprox),epsilon);
      }
      return String.format("[%d, %1.10f]",n,4*piAprox);
    }
}
javatlacati
http://javapro.org

javapro.org