Números perfectos (lenguaje C)

Iniciado por NOB2014, 25 Septiembre 2014, 20:05 PM

0 Miembros y 3 Visitantes están viendo este tema.

NOB2014

Hola, buen día.-
engel lex realmente una genialidad lo tuyo, me allano mucho el camino y gracias a todos los que propusieron algo parecido y al resto.-

#include <stdio.h>
#include <math.h>


void primo(void);
void perfecto(int num);

int main(void){

primo();

printf("\n\n");
return 0;
}

void primo(void){
int num,j, a=0;
for(num=0; num<=13; num++){
for(j=1; j<=num; j++){
if(num%j==0){
a++;
}
}
if(a==2){
perfecto(num);
}
a=0;
}
}

void perfecto(int num){
int auxUno=0, auxDos=0;
char perfecto[100];
auxUno = pow(2,num-1);
auxDos = pow(2,num)-1;
sprintf(perfecto,"%d", auxUno * auxDos);

printf("\n %s ", perfecto);
}


     

Lo que me traen son 2 consultas:
La primera es, porque el error del quinto número perfecto, según estas 2 páginas el quinto  debería ser 33 550 336 y a mí me sale en el sexto lugar.- 
http://es.wikipedia.org/wiki/N%C3%BAmero_perfecto
http://curiotecnology.blogspot.com.ar/2012/05/los-5-numeros-perfectos-java.html
La segunda, ¿se puede poner los dos resultado (auxUno y auxDos) en un arreglo de char y multiplicarlos para alojarlo en la variable perfecto?, esto me surge porque el séptimo número perfecto no cabe en una variable del tipo int.-
Espero haberme explicado lo suficiente.-

Saludos.
Daniel   
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

engel lex

#11
el quito numero es algo que no había leido, la forma da los perfectos cuando n es primo... y diferente de 11, aparentemente 11 es el unico primo no perfecto... disculpas por lo haber visto eso D:

este es mi código usando desplazamiento de bits solo por muestra como sería según yo  ;)

comentado y usando iostream porque me da pereza el printf  ;D

no uso el metodo 2 pero funciona

#include <stdio.h>

long unsigned int numero_perfecto_metodo1(int primo);
long unsigned int numero_perfecto_metodo2(int primo);
bool es_primo(int numero);

int main(void){
unsigned long int perfecto;//para 64 bits completos de precision
int actual;
for(actual = 2; actual <=31; actual++){ //recorre primos del 2 al 27
if(actual==11)actual = 13; //descarto el error del 11
if(es_primo(actual)){ //si el numero actual es primo
perfecto = numero_perfecto_metodo1(actual); //evaluo
printf("%d = resultado:\t %lu \n",actual,perfecto);
}
}
return 0;
}
long unsigned int numero_perfecto_metodo1(int primo){
unsigned long int resultado;
resultado = 1<<(primo-1);
resultado *= (1<<primo)-1;//a*=b es lo mismo que a= a*b
return resultado;
}
long unsigned int numero_perfecto_metodo2(int primo){
unsigned long int resultado;
resultado = (unsigned long int)((1<<primo)-1)<<(primo-1);//necesita casting (?)
return resultado;
}
bool es_primo(int numero){
if(numero == 2) return true; //2 es primo
if(numero % 2 == 0) return false; //ningun multiplo de 2 es primo
int prueba;
for(prueba = 3;prueba*prueba < numero; prueba+=2){ //solo hasta la raiz
if(numero%prueba==0) return false; //si tiene multiplo no es primo
}
return true; //entonces si es primo
}


ese metodo de primos está bien documentado aquí en el foro, un numero para saber primo solo hay que investigar hasta su raiz, más allá todo se repite, al excluir los 2 al final el tiempo de calculo se baja desde "n" ciclos hasta "raiz(n) /2" ciclos ej, el 1.000.001 baja de ser 1.000.001 ciclos hasta 500...

para ser sincero se que el metodo 2 necesita casting de tipo, pero no estoy seguro por que...
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

NOB2014

Hola.
Con el siguiente programita queda demostrado que el 11 primo no es un número perfecto.-

#include <stdio.h>

int main(void){
int a = 33550336, i, res=0;
printf("\n\n");
for(i=1; i<100000000; i++){
if(a%i == 0){
res += i;
if(a == res){
printf("%10d \n ========== \n%10d", i, res);
break;
}
else{
printf("%10d\n", i);
}
}
}

printf("\n\n");
return 0;
}


En el caso del programa tuyo lamentablemente no lo voy a poder correr porque desconozco totalmente C++, me gustaría saber cuál es el perfecto más grande que logras, pero bueno...

Saludos.
Daniel   
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

engel lex

#13
ya, puedes copiar de mi ultimo post, modificadas 3 lineas del codigo para hacerlo 100% c  ;D

en
printf("%d = resultado:\t %lu \n",actual,perfecto);

\t es una tabulacion para un espaciador "justificado"
%lu es para imprimir un long unsigned int (%u es unsigned int, %l es long int y se mezclan en uno)
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

NOB2014

Hola.
Por suerte no puedo ver el movimiento de tus manos ni el gesto de tú cara al leerme nuevamente, tenele un poco de paciencia al "abuelo" Daniel.- ;D ;D ;D
Me podría decir como corregir los siguiente errores, según tengo leído true y false no existen en c.-



Saludos.
Daniel   
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

engel lex

oh... sorry! :P ya voy a arreglarlo, casi no trabajo en c y olvido que no tiene booleanos  :-X

#include <stdio.h>
#define true 1
#define false 0
long unsigned int numero_perfecto_metodo1(int primo);
long unsigned int numero_perfecto_metodo2(int primo);
int es_primo(int numero);

int main(void){
unsigned long int perfecto;//para 64 bits completos de precision
int actual;
for(actual = 2; actual <=31; actual++){ //recorre primos del 2 al 27
if(actual==11)actual = 13; //descarto el error del 11
if(es_primo(actual)){ //si el numero actual es primo
perfecto = numero_perfecto_metodo1(actual); //evaluo
printf("%d = resultado:\t %lu \n",actual,perfecto);
}
}
return 0;
}
long unsigned int numero_perfecto_metodo1(int primo){
unsigned long int resultado;
resultado = 1<<(primo-1);
resultado *= (1<<primo)-1;//a*=b es lo mismo que a= a*b
return resultado;
}
long unsigned int numero_perfecto_metodo2(int primo){
unsigned long int resultado;
resultado = (unsigned long int)((1<<primo)-1)<<(primo-1);//necesita casting (?)
return resultado;
}
int es_primo(int numero){
if(numero == 2) return true; //2 es primo
if(numero % 2 == 0) return false; //ningun multiplo de 2 es primo
int prueba;
for(prueba = 3;prueba*prueba < numero; prueba+=2){ //solo hasta la raiz
if(numero%prueba==0) return false; //si tiene multiplo no es primo
}
return true; //entonces si es primo
}


cambié bool por int y definí true y false
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

Blaster

Para generar los cinco números perfectos conocidos (6, 28, 496, 8128, 33550336) con la formula de  Euclides es necesario trabajar con los primos de mersenne (2, 3, 5, 7, 13)  aquí un ejemplo :

Código (cpp) [Seleccionar]
#include <math.h>
#include <stdio.h>
#include <limits.h>

typedef enum { FALSE = 0, TRUE = 1 } BOOL;

BOOL is_prime( int p )
{
    if( p == 2 ) return TRUE;
    else if( p <= 1 || p % 2 == 0 ) return FALSE;
    else
    {
        BOOL prime = TRUE;
        const int to = sqrt(p);
        int i;
        for(i = 3; i <= to; i+=2)
            if (!(prime = p % i))break;
        return prime;
    }
}

BOOL is_mersenne_prime( int p )
{
    if( p == 2 )
        return TRUE;
    else
    {
        unsigned m_p = ( 1U << p ) - 1;
        unsigned s = 4;
        int i;
        for (i = 3; i <= p; i++)
            s = (s * s - 2) % m_p;
        return s == 0;
    }
}

int main(void)
{
    int p;

    for( p = 2; p <= 13; p += 1 )
        if( is_prime(p) && is_mersenne_prime(p) )
           numero_perfecto(p);
           /*printf("%d ", p);*/
    printf("\n");

    return 0;
}


Un Saludo

engel lex

Blaster seguro que solo con los primos de mersenne?

es decir...son los numeros tal que


Citarwhere p is assumed prime.

entonces la secuencia da
Citar22-1 = 3
23-1 = 7
25-1 = 31

no están el 2, 5, 13, 17,23... sin embargo son tomados en la secuencia de los perfectos... así que creo que la teoría es incorrecta
El problema con la sociedad actualmente radica en que todos creen que tienen el derecho de tener una opinión, y que esa opinión sea validada por todos, cuando lo correcto es que todos tengan derecho a una opinión, siempre y cuando esa opinión pueda ser ignorada, cuestionada, e incluso ser sujeta a burla, particularmente cuando no tiene sentido alguno.

Blaster

Cita de: engel lex en 27 Septiembre 2014, 22:28 PM
Blaster seguro que solo con los primos de mersenne?

entonces la secuencia da
no están el 2, 5, 13, 17,23... sin embargo son tomados en la secuencia de los perfectos... así que creo que la teoría es incorrecta

Con el algoritmo que propuse por supuesto se obtienen esa secuencia de primos menos el 23 el cual no forma parte de la secuencia de números perfectos en ves debes incluir el tres. Estoy utilizando la prueba de Lucas-Lehmer :

http://es.wikipedia.org/wiki/Test_de_Lucas-Lehmer

Para descartar todos los primos no valido, por otra parte en la función es_primo en tu código tienes un pequeño error la condición del for debe quedar así

Código (cpp) [Seleccionar]
prueba*prueba <= numero

Debido a esto validaba el nueve como un primo



NOB2014

Hola.
Estoy de acuerdo y con esa modificación los primos están correctos pero los perfectos me parece que no.-



Saludos.
Daniel   
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-