elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Los 10 CVE más críticos (peligrosos) de 2020


  Mostrar Mensajes
Páginas: 1 ... 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 [1548] 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 ... 1750
15471  Foros Generales / Noticias / Re: El Ministerio de Fomento recuerda la prohibición del uso comercial de los drones en: 10 Abril 2014, 04:32 am
NADA de tomas aéreas he dicho! XD
15472  Programación / Programación C/C++ / Re: Calculo de pi en alta precisión (aporte) en: 10 Abril 2014, 01:25 am
gracias do-while! :P vamos con esa! voy a extender el programa... ya llegué a mi casa, tengo 1,5l de te negro listos y 250g de maní japonés! ese código sale en un rato! :P
15473  Programación / Programación C/C++ / Re: Calculo de pi en alta precisión (aporte) en: 9 Abril 2014, 21:30 pm
ikillnukes tambien a eso voy, segundo argumento sin salida, solo para ver el tiempo del calculo, los decimales calculados correctos no es tan simple fijate que yo genero decimales de mas, para asegurar el valor correcto, si ves.el metodo de euler ves que casi siempre da decimales periódicos

próximo a probar:salida concatenada a archivo, tiempo de ejecución, alguna sugerencia?
15474  Programación / Programación C/C++ / Re: Calculo de pi en alta precisión (aporte) en: 9 Abril 2014, 20:57 pm
en realidad no me preocupé del cout porque la diferencia ue causa es baja, si calculan 10000 decimales, haces unos 33000 calculos con 3 variables de 35kb xD e imprimir 35kb no toma sino unas décimas de segundo por lento que sea :p pero lo voy a hacer con printf me dió pereza hacerlo anoche

por otro lado no se puede hacet cifra a cifra ya que el resultado es la combinación de factoriales sumatorias y potencias, el numero siempre debe debe ser reusado
15475  Programación / Programación C/C++ / Calculo de pi en alta precisión (aporte) en: 9 Abril 2014, 08:16 am
Buenas, en estos días estaba por aquí un alguien preguntando sobre un programa básico con pi, por cosas de la vida, decidí ahondar en el tema... calcular pi con alta precisión...

deja claro que el siguiente tema no lo hago en pro de discutir la naturaleza de pi, ni nada al respecto, es solo en pro del calculo de alta precisión ;)

aquí básicamente solo hay 2 temas importantes que abordar

-¿qué formula usar?
-¿como calculo números en alta precisión?

con lo primero... la formula, decidí usar la de euler

escogí esta por su precisión y su relativamente fácil aplicación

para aplicarla la tenemos que separar en 2 partes por su sumatoria y su factorial...


Código
  1. sumatoria = factorial = 1;
  2. for(i=1;i<ciclos;i++){
  3.    factorial *= i/(i*2+1);
  4.    sumatoria += factorial;
  5. }
  6. sumatoria *=2;
  7. pi = sumatoria
  8.  

ahí resolvemos esa formula básicamente... pero nos damos cuenta de un problema... los numeros double están limitados a 64 bits... unos 20 decimales para nuestro caso...

en este caso viene la aritmetica de alta precisión, GMP... aquí en el foro buscaba como usarlo... al final conseguí y publiqué el como...

este usa unidades especificas y operaciones especificas para alta precisión...

doy una ligera explicación de lo usado... no voy a caer en mucho detalle de las funciones...
mpf_t es una variable de tipo "float" propia
mpf_set_default_prec da el valor en bytes que la variable usará
mpf_init_set_str inicializa las variables desde un string... por que un string? porque quise -.-... se hay que inicializar las variables obligatoriamente

mpf_set_ui da un valor desde un entero sin signo a un float
div= division, mul = multiplicaccion, add= adición

mpf_get_str convierte de float de GMP a char* (string)

como no habia una multiplicacion / asignacion directa, me tocó usar una variable de intercambio


ahora la parte interesante... el codigo  ;-)

hice un pequeño/bonito formato de impresión de 10 en 10 dígitos... en  lineas de 50 y bloques de 500 con el numero de dígito como indicador... probé solo hasta 40.000 dígitos, comprobando en internet precisos... pero en 5min 9 seg! :P es mi único intento en este campo... no esperen romper el record mundial de decimales ;P por cierto... de ahí en adelante, los dígitos son cuesta arriba... así que cuidado con el tiempo... pueden usar el programa pasando el numero de dígitos como argumento... los dígitos los toma en cuanta de 100 en 100

pd: la precisión la hago como  "precision = digitos * 100 * 3 * 1.12" porque descubrí que se requieren 3 ciclos por dígito correcto sobre los 100 con un 12% de error (calculado a ojo) :P


---------------------------------------------------------------codigo final con formulas a partir de aqui---------------------------------------------------------------

librerias
Código
  1. #include <iostream>
  2. #include <stdlib.h>
  3. #include <string>
  4. #include <gmp.h>
  5. #include <gmpxx.h>
  6. #include <time.h>
  7. #include <sstream>
  8. using namespace std; // :P
  9.  

prototipos
Código
  1. string metodo_euler(unsigned long int digitos, mp_exp_t &exponente);
  2. string metodo_ramanujan(unsigned long int digitos, mp_exp_t &exponente);
  3. void imprimir_pi_aux(string pi, mp_exp_t exponente, int digitos);

main
Código
  1. int main(int argc, char **argv) {
  2.    unsigned long int digitos = strtol(argv[1], NULL, 10); //argv a int
  3.    mpf_set_default_prec(32 * 10 * (digitos / 100) * 1.11); //precision + 10%
  4.    long exponente;
  5.    clock_t start = clock();
  6.    string pi;
  7.    int metodo = 0;
  8.    int i = 1;
  9.    for (i = 0; i < argc; i++) {
  10.        if (argv[i][0] == '-') {
  11.            switch (argv[i][1]) {
  12.                case 'e':
  13.                    metodo = 0;
  14.                    break;
  15.                case 'r':
  16.                    metodo = 1;
  17.                    break;
  18.            }
  19.        }
  20.    }
  21.    switch (metodo) {
  22.        case 0:
  23.            cout << "imprimiendo por metodo Euler, " << digitos * 3 * 1.12 << " ciclos"<<endl;
  24.            pi = metodo_euler(digitos, exponente);
  25.            break;
  26.        case 1:
  27.            cout << "imprimiendo por metodo Ramanujan, " << (int) (digitos / 8 * 1.01) << " ciclos"<<endl;
  28.            pi = metodo_ramanujan(digitos, exponente);
  29.            break;
  30.    }
  31.  
  32.    clock_t end = clock();
  33.  
  34.    imprimir_pi_aux(pi, exponente, digitos);
  35.    cout << "\ntiempo total de ejecucion: " << (float) (end - start) / CLOCKS_PER_SEC << "\n";
  36.    cout << "tiempo total de impresion: " << (float) (clock() - end) / CLOCKS_PER_SEC << "\n\n";
  37.    return 0;
  38. }

tiene 2 argumentos... primero los digitos (obligatorio)... luego -r para ramanujan o -e para euler (opcional, euler predeterminado)

imprimir_pi_aux

para tener un formato único de impresión para todo

Código
  1. void imprimir_pi_aux(string pi, long exponente, int digitos) {
  2.    cout << "Pi: ";
  3.    stringstream aux;
  4.    unsigned long int i;
  5.    if (exponente <= 0) {
  6.        cout << "0.";
  7.        while (exponente < 0) {
  8.            cout << 0;
  9.            exponente++;
  10.        }
  11.    } else {
  12.        for (i = 0; i < exponente; i++) {
  13.            cout << pi[i];
  14.        }
  15.        cout << ".\n\n1:\t";
  16.    }
  17.    for (i = exponente; i < digitos + 1; i++) {
  18.        aux << pi[i];
  19.        if ((i - exponente + 1) % 10 == 0) aux << ' ';
  20.        if ((i - exponente + 1) % 500 == 0) aux << endl;
  21.        if ((i - exponente + 1) % 50 == 0 && i < digitos) aux << endl << i + 1 << ":\t";
  22.    }
  23.    aux << endl;
  24.    cout << aux.str();
  25. }
aux por consejo de amchacon

metodo_euler

corto, simple, pero largo... para 10.000 dígitos 33.600 ciclos o para mi unos 11 seg

basado en la formula



Código
  1. string metodo_euler(unsigned long int digitos, long &exponente) {
  2.    digitos /= 100; //trabaja con lotes de 100
  3.    unsigned long int precision = digitos * 100 * 3 * 1.12;
  4.    unsigned long int x, i;
  5.    mpf_t factorial, sumatoria, buff_factorial; //variables GMP
  6.    mpf_init_set_ui(factorial, 1); //factorial=1
  7.    mpf_init_set_ui(sumatoria, 1); //sumatoria=1
  8.    mpf_init_set_ui(buff_factorial, 1); //buff_factorial=1
  9.  
  10.    for (x = 1; x < precision; x++) {
  11.        i = 2 * x + 1;
  12.        mpf_set_ui(buff_factorial, x); //buff_factorial=x
  13.        mpf_div_ui(buff_factorial, buff_factorial, i); //buff_factorial*=i
  14.        mpf_mul(factorial, factorial, buff_factorial); //factorial*=buff_factorial
  15.        mpf_add(sumatoria, sumatoria, factorial); //sumatoria+=factorial
  16.    }
  17.    mpf_mul_ui(sumatoria, sumatoria, 2); //sumatoria*=2
  18.    return mpf_get_str(NULL, &exponente, 10, 0, sumatoria);
  19. }

metodo_ramanujan

por consejo de do-while, basado en la formula

eficiente, pero dificil de aplicar (si no, miren el codigo de abajo)
para 10.000 digitos 1.262 ciclos en 1.1 segundos



Código
  1. string metodo_ramanujan(unsigned long int digitos, long &exponente) {
  2.    digitos /= 8;
  3.    digitos *= 1.01;
  4.    unsigned long int i, j;
  5.    mpf_t sumatoria, buff_sumatoria, buff_ciclo_superior, buff_ciclo_inferior, primera_parte,
  6.            buff_ciclo_inferior2, factorial_superior, factorial_inferior;
  7.    mpf_init_set_ui(sumatoria, 1103); //sumatoria=0
  8.    mpf_init_set_ui(buff_sumatoria, 0); //buff_sumatoria=0
  9.    mpf_init_set_ui(buff_ciclo_superior, 0); //buff_ciclo_superior=0
  10.    mpf_init_set_ui(buff_ciclo_inferior, 0); //buff_ciclo_inferior=0
  11.    mpf_init_set_ui(primera_parte, 0); //primera_parte=0
  12.    mpf_init_set_ui(buff_ciclo_inferior2, 0); //buff_ciclo_inferior2=0
  13.    mpf_init_set_ui(factorial_superior, 1); //factorial_superior=1
  14.    mpf_init_set_ui(factorial_inferior, 1); //factorial_inferior=1
  15.    mpf_sqrt_ui(primera_parte, 2); //primera_parte=sqrt(2)
  16.    mpf_mul_ui(primera_parte, primera_parte, 2); //primera_parte*=2
  17.    mpf_div_ui(primera_parte, primera_parte, 9801); //primera_parte/=9801
  18.  
  19.    for (i = 1; i <= digitos; i++) {
  20.        for (j = (i - 1)*4 + 1; j <= i * 4; j++) {
  21.            mpf_mul_ui(factorial_superior, factorial_superior, j);
  22.        }
  23.        mpf_set_ui(buff_ciclo_superior, 26390);
  24.        mpf_mul_ui(buff_ciclo_superior, buff_ciclo_superior, i);
  25.        mpf_add_ui(buff_ciclo_superior, buff_ciclo_superior, 1103);
  26.        mpf_mul(buff_ciclo_superior, buff_ciclo_superior, factorial_superior);
  27.        mpf_mul_ui(factorial_inferior, factorial_inferior, i);
  28.        mpf_pow_ui(buff_ciclo_inferior, factorial_inferior, 4);
  29.        mpf_set_ui(buff_ciclo_inferior2, 396);
  30.        mpf_pow_ui(buff_ciclo_inferior2, buff_ciclo_inferior2, 4 * i);
  31.        mpf_mul(buff_ciclo_inferior, buff_ciclo_inferior, buff_ciclo_inferior2);
  32.        mpf_div(buff_sumatoria, buff_ciclo_superior, buff_ciclo_inferior);
  33.        mpf_add(sumatoria, sumatoria, buff_sumatoria);
  34.  
  35.    }
  36.    mpf_mul(sumatoria, sumatoria, primera_parte);
  37.    mpf_ui_div(sumatoria, 1, sumatoria);
  38.    return mpf_get_str(NULL, &exponente, 10, 0, sumatoria);
  39. }
15476  Foros Generales / Foro Libre / Re: Ayuda urgente con chico desaparecido en: 9 Abril 2014, 04:41 am
localizar la ubicación... no... ni si quiera el mismo fb lo podría saber... la operadora es quien podría dar más seguridad pero dudo que nada más preciso que un circulo en un par de km de radio :stal vez si el teléfono es samsung o alguna marca importante, la empresa podría intentarlo...
15477  Sistemas Operativos / Windows / Re: ¡¡¡NO ACTUALICES XP O CAERAS EN UNA TRAMPA DIFÍCIL DE SALIR!!! en: 9 Abril 2014, 04:26 am
efectivamente apoyo a Eternal Idol...
15478  Sistemas Operativos / Windows / Re: ¡¡¡NO ACTUALICES XP O CAERAS EN UNA TRAMPA DIFÍCIL DE SALIR!!! en: 9 Abril 2014, 04:22 am
no coloques los títulos en mayúsculas! -.-
15479  Seguridad Informática / Hacking / Re: software con candado en: 8 Abril 2014, 06:35 am
no escribas en mayúsculas... :s es de "mal gusto", busca en el foro en la sección de ingeniería inversa los tutoriales
15480  Foros Generales / Dudas Generales / Re: conversiones en: 8 Abril 2014, 05:55 am
cierto! XD pensé que era el foro de programación general! XD leí mal!


puedes aplicar la de  Gh057... y para hex y oct es facil desde binario :P para octal agarras de 3 en 3 bits de binario, para hex agarras de 4 en 4
Páginas: 1 ... 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 [1548] 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 ... 1750
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines