0 3 mins 1 semana

Seguramente todos los lectores han oído mencionar este número denominado con la letra griega π (Pi). Frecuentemente utilizado por los matemáticos, físicos, arquitectos e ingenieros, nos ha devuelto tanto soluciones como fuertes dolores de cabeza. A continuación publicamos un algoritmo que permite calcular el valor exacto de Pi hasta 10 000 cifras decimales; lo demás sólo depende del nivel de procesamiento de la computadora donde se ejecute el programa.

#include <iostream>
#include <fstream>
#include <cstdio>

using namespace std;

/*
Calculando un gran número:
Elaborado por Harvin Manuel Toledo
Basado en la página de: Xavier Gourdon
harvin_t@hotmail.com, harvin_t@yahoo.es

Empleé dos formulas para comprobar que el programa no se equivoca:
pi=4*(4*arctan(1/5)-arctan(1/239))
pi=4*(arctan(1/2)+arctan(1/3))
y usando la fórmula arctan(x)=x-x^3/3+x^5/5-x^7/7+x^9/9. Esta es llamada también
la serie de Leibniz.
Para hacer un cálculo más rápido podemos usar las identidades
siguientes para comprobar nuestro cálculos

Estas fórmulas fueron usadas por Yasumasa Kanada en el récord que rompió en 2002
en Tokio, Japón con más de un billón de cifras de Pi
pi=48*arctan(1/49)+128*arctan(1/57)-20*arctan(1/239)+48*arctan(1/110443)
pi=176*arctan(1/57)+28*arctan(1/239)-48*arctan(1/682)+96*arctan(1/12943)
*/

//definir la base en la que se harán las operaciones

const long B=10000;
const long LB=4;
const long Digitos=10000; //si alteras este número obtendrás más digitos

//Declaraciones
void Imprimir(long, long *);
void Archivar(long, long *);
void Mult(long, long *, long);
void Div(long, long *, long);
void Sum(long , long *, long *);
void Rest(long , long *, long *);
void HacerEntero(long, long *, long);
bool EsCero(long, long *);

int main()
  {
  bool signo;
  long *arctan1, *arctan2, *pi, *term;
  long k;
  long tam;

  tam=Digitos/LB+1;
  arctan1=new long[tam];
  arctan2=new long[tam];
  pi=new long[tam];
  term=new long[tam];

  cout<<"Memoria reservada con éxito"<<endl;
  cout<<"El programa ha comenzado a calcular, espere un momento..."<<endl;

  HacerEntero(tam, arctan1, 0);
  HacerEntero(tam, arctan2, 0);
  HacerEntero(tam, pi, 0);

  k=1;
  signo=false;
  HacerEntero(tam, term, 1);
  Div(tam, term, 5);
  Sum(tam, arctan1, term);
  while(!EsCero(tam, term))
  {
    Div(tam, term, 25);
    Div(tam, term, 2*k+1);
    if(signo)
    Sum(tam, arctan1, term);
    else
    Rest(tam, arctan1, term);
    if(signo)
    signo=false;
    else
    signo=true;
    Mult(tam, term, 2*k+1);
    k++;
  }
  Mult(tam, arctan1, 4);

  k=1;
  signo=false;
  HacerEntero(tam, term, 1);
  Div(tam, term, 239);
  Sum(tam, arctan2, term);
  while(!EsCero(tam, term))
  {
    Div(tam, term, 57121);
    Div(tam, term, 2*k+1);
    if(signo)
    Sum(tam, arctan2, term);
    else
    Rest(tam, arctan2, term);
    if(signo)
    signo=false;
    else
    signo=true;
    Mult(tam, term, 2*k+1);
    k++;
  }

  Sum(tam, pi, arctan1);
  Rest(tam, pi, arctan2);
  Mult(tam, pi, 4);

  Imprimir(tam, pi);
  Archivar(tam, pi);
  cin.ignore();

  delete[] arctan1;
  delete[] arctan2;
  delete[] term;
  delete[] pi;
}

void Imprimir(long n, long *x)
{
  long i=0;

  printf("%d.", x[0]);
  for(i=1; i<n-1; i++)
  printf("%.4d", x[i]);
}

void Archivar(long n, long *x)
{
  FILE *pArchivo;

  pArchivo=fopen("pi.txt", "w");
  long i=0;

  fprintf(pArchivo, "Elaborado por harvin toledo\n");
  fprintf(pArchivo, "El valor pi es: ");
  fprintf(pArchivo, "%d.", x[0]);

  for(i=1; i<n-1; i++)
  fprintf(pArchivo, "%.4d", x[i]);
  fclose(pArchivo);
}

/* Esta función multiplica un gran número por un entero común
no mayor que sizeof(long),
el resultado es almacenado en el mismo x
*/
void Mult(long n, long *x, long q)
{
  long i=0;
  long lleva=0, xi;

  for(i=n-1; i>=0; i--)
  {
    xi=x[i]*q+lleva;
    if(xi>B)
    {
      lleva=xi/B;
      xi-=lleva*B;
    }
    else
    lleva=0;
    x[i]=xi;
  }

  x[0]+=lleva*B;
}

/* Esta funcion divide un gran número por un entero común
no mayor que sizeof(long)
el resultado es almacenado en el mismo x
*/
void Div(long n, long *x, long q)
{
  long i, lleva=0, xi;
  
  for(i=0; i<n; i++)
  {
    xi=x[i]+lleva*B;
    x[i]=xi/q;
    lleva=xi-x[i]*q;
  }
}

/* Esta función suma un gran número en multiprecisión con otro
del mismo tipo y el resultado lo almacena en el primero o sea x
*/
void Sum(long n, long *x, long *y)
{
  long i, lleva=0;
  for(i=n-1; i>=0; i--)
  {
    x[i]+=y[i]+lleva;
    if(x[i]>=B)
    {
      x[i]-=B;
      lleva=1;
    }
  else
  lleva=0;
  }
}

/*Esta función resta dos números en multiprecisión
y almacena el nuevo resultado en el primero*/

void Rest(long n, long *x, long *y)
{
  long i, lleva=0;
  for(i=n-1; i>=0; i--)
  {
    x[i]=x[i]-y[i]-lleva;
    if(x[i]<0)
    {
      x[i]+=B;
      lleva=1;
    }
  else
  lleva=0;
  }
}

/*Esta función convierte un entero menor que sizeof(long),
en un entero con multiprecisión*/
void HacerEntero(long n, long *x, long Entero)
{
  long i;
  x[0]=Entero;
  for(i=1; i<n; i++)
  x[i]=0;
}

//Esta función averigua si un número en multiprecisión
//es igual a cero o no
bool EsCero(long n, long *x)
{
  long i;
  for(i=0; i<n; i++)
  {
    if(x[i])
    return false;
  }
  return true;
}

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *