la ecuación de Ramanujan es una locura @.@ es un poco dificil de aplicar... sin embargo dudo de su eficiencia al momento de procesar, ya que a diferencia de la de euler es muy compleja, tiene 2 factoriales diferentes (y el de arriba es grande, con k = 3 el valor es de 479.001.600) la de abajo tiene 2 potencias y la segunda es de 4*k, haciéndola sin funciones matemáticas precompiladas sería
for(i=1;i<precision;i++){
for(j=1;j<=4*i;j++){
factorial1*=j;
}
for(j=1;j<=i;j++){
factorial2*=j;
}
for(j=1;j<=4;j++){
factorial2*=factorial2;
}
for(j=1;j<=4*i;j++){
divisor*=396;
}
sumatoria+=(factorial1*(1103+26390*i))/(factorial2*divisor)
}
sumatoria=1/sumatoria
el código sobre eso se puede optimizar pero igual son muchos ciclos dentro de cada ciclo (cuando precision = 1.000; tendrá que hacer por lo menos 4.000.000 de ciclos secundarios los cuales multiplicarán valores muy grandes, esto sin contar que sería solo para obtener 8.000 dígitos teóricos...)
la de euler es simple y hasta bonita XD solo requiere en ciclo principal y unas pocas operaciones
aqui la formula de Ramanujan
cambié un poco el programa para hacerlo más modular...
ya se me hizo tarde... así que ni argumentos (más que ramanujan), ni corrida silenciosa, ni salida a archivo!
sorry por ahora... estoy cansado
agregado por ahora, ramanujan (no da pi... si alguien me ayuda con esto, sobre donde me equivoco...), tiempo de calculo e impresion
por cierto amchacon sobre el tiempo de impresión incluso a 40.000 decimales la diferencia es instrumental, no llega al medio segundo de diferencia
aquí el código... se está tornando largo D:
#include <iostream>
#include <stdlib.h>
#include <string>
#include <gmp.h>
#include <gmpxx.h>
#include <time.h>
#include <sstream>
using namespace std;
string metodo_euler(unsigned long int digitos, mp_exp_t &exponente);
string metodo_ramanujan(unsigned long int digitos, mp_exp_t &exponente);
void imprimir_pi_aux(string pi, mp_exp_t exponente, int digitos);
int main(int argc, char **argv) {
unsigned long int digitos = strtol(argv[1], NULL, 10); //argv a int
mpf_set_default_prec(32 * 10 * (digitos / 100) * 1.11); //precision + 10%
long exponente;
clock_t start = clock();
string pi;
if(argc>2 && argv[2]=="ramanujan"){
pi = metodo_ramanujan(digitos, exponente);
}else{
pi = metodo_euler(digitos, exponente);
}
clock_t end = clock();
imprimir_pi_aux(pi, exponente, digitos);
cout << "\ntiempo total de ejecucion: " << (float) (end - start) / CLOCKS_PER_SEC << "\n";
cout << "tiempo total de impresion: " << (float) (clock() - end) / CLOCKS_PER_SEC << "\n\n";
return 0;
}
void imprimir_pi_aux(string pi, long exponente, int digitos) {
cout << "PI: ";
stringstream aux;
unsigned long int i;
if (exponente < 0) {
cout << "0.";
while (exponente < 0) {
cout << 0;
exponente++;
}
} else {
for (i = 0; i < exponente; i++) {
cout << pi[i];
}
cout << ".\n\n1:\t";
}
for (i = exponente; i < digitos + 1; i++) {
aux << pi[i];
if (i % 10 == 0) aux << ' ';
if (i % 500 == 0) aux << endl;
if (i % 50 == 0 && i < digitos) aux << endl << i + 1 << ":\t";
}
aux << endl;
cout << aux.str();
}
string metodo_euler(unsigned long int digitos, long &exponente) {
digitos /= 100; //trabaja con lotes de 100
unsigned long int precision = digitos * 100 * 3 * 1.12;
unsigned long int x, i;
mpf_t factorial, sumatoria, buff_factorial; //variables GMP
mpf_init_set_ui(factorial, 1); //factorial=1
mpf_init_set_ui(sumatoria, 1); //sumatoria=1
mpf_init_set_ui(buff_factorial, 1); //buff_factorial=1
for (x = 1; x < precision; x++) {
i = 2 * x + 1;
mpf_set_ui(buff_factorial, x); //buff_factorial=x
mpf_div_ui(buff_factorial, buff_factorial, i); //buff_factorial*=i
mpf_mul(factorial, factorial, buff_factorial); //factorial*=buff_factorial
mpf_add(sumatoria, sumatoria, factorial); //sumatoria+=factorial
}
mpf_mul_ui(sumatoria, sumatoria, 2); //sumatoria*=2
return mpf_get_str(NULL, &exponente, 10, 0, sumatoria);
}
string metodo_ramanujan(unsigned long int digitos, long &exponente) {
unsigned long int i, j;
mpf_t sumatoria, buff_sumatoria, buff_ciclo_superior, buff_ciclo_inferior, primera_parte,
buff_ciclo_inferior2, factorial_superior, factorial_inferior;
mpf_init_set_ui(sumatoria, 1103); //sumatoria=0
mpf_init_set_ui(buff_sumatoria, 0); //buff_sumatoria=0
mpf_init_set_ui(buff_ciclo_superior, 0); //buff_ciclo_superior=0
mpf_init_set_ui(buff_ciclo_inferior, 0); //buff_ciclo_inferior=0
mpf_init_set_ui(primera_parte, 0); //primera_parte=0
mpf_init_set_ui(buff_ciclo_inferior2, 0); //buff_ciclo_inferior2=0
mpf_init_set_ui(factorial_superior, 1); //factorial_superior=1
mpf_init_set_ui(factorial_inferior, 1); //factorial_inferior=1
mpf_sqrt_ui(primera_parte, 2); //primera_parte=sqrt(2)
mpf_mul_ui(primera_parte, primera_parte, 2); //primera_parte*=2
mpf_div_ui(primera_parte, primera_parte, 9801); //primera_parte/=9801
for (i = 1; i <= digitos; i++) {
mpf_set_ui(factorial_superior, 1);
for (j = 2; j <= i * 4; j++) {
mpf_mul_ui(factorial_superior, factorial_superior, j);
}
mpf_set_ui(buff_ciclo_superior, 26390);
mpf_mul_ui(buff_ciclo_superior, buff_ciclo_superior, i);
mpf_add_ui(buff_ciclo_superior, buff_ciclo_superior, 1103);
mpf_mul(buff_ciclo_superior, buff_ciclo_superior, factorial_superior);
mpf_mul_ui(factorial_inferior, factorial_inferior, i);
mpf_pow_ui(buff_ciclo_inferior, factorial_inferior, 4);
mpf_set_ui(buff_ciclo_inferior2, 396);
mpf_pow_ui(buff_ciclo_inferior2, buff_ciclo_inferior2, 4 * i);
mpf_mul(buff_ciclo_inferior, buff_ciclo_inferior, buff_ciclo_inferior2);
mpf_div(buff_sumatoria, buff_ciclo_superior, buff_ciclo_inferior);
mpf_add(sumatoria, sumatoria, buff_sumatoria);
}
mpf_mul(sumatoria, sumatoria, primera_parte);
mpf_ui_div(sumatoria, 1, sumatoria);
return mpf_get_str(NULL, &exponente, 10, 0, sumatoria);
}