Foros del Web » Programación para mayores de 30 ;) » C/C++ »

[SOLUCIONADO] duda para sacar factorial de un numero

Estas en el tema de duda para sacar factorial de un numero en el foro de C/C++ en Foros del Web. He hecho un programa que me devuelve el factorial de un numero, pero a partir del numero 34 todos los demás factoriales me dan 0, ...
  #1 (permalink)  
Antiguo 15/02/2015, 15:27
 
Fecha de Ingreso: febrero-2015
Mensajes: 20
Antigüedad: 9 años, 2 meses
Puntos: 0
Pregunta duda para sacar factorial de un numero

He hecho un programa que me devuelve el factorial de un numero, pero a partir del numero 34 todos los demás factoriales me dan 0, y otros números salen negativos como el 33,32,29,28,26,24,22 y otros pocos salen bien, aquí esta el código:

Código:
#include <stdio.h>

int main ()
{
	int num;  //numero introducido
	int ni, n;  //factorial
	
	printf("Introduzca numero, (-1 para terminar): ");
	scanf("%d", &num);
	
	while (num != -1){
	if (num == 0){
		ni = 1;
	}
	else if (num == 1){
		ni = 1;
	}
	else{
	
	n = num;
	ni = n * (n-1);   //ni es "n!"
	--n;
	while (n != 1){  //sacar factorial de numero mayor a 2
		
		ni = ni * (n-1);
		n -= 1;
		
	}
  }
     printf("El factorial de %d es %d\n", num, ni);
  
     printf("Introduzca numero, (-1 para terminar): ");
     scanf("%d", &num);
   
}
  

	
	system("pause");
	return 0;	
}
Lo de los números que me dan cero, no se si sera porque la variable tenga un limite de almacenamiento, pero lo de los factoriales negativos, no me lo explico.
¿Tengo mal el código?

Última edición por braedu555; 15/02/2015 a las 15:33
  #2 (permalink)  
Antiguo 15/02/2015, 16:37
Avatar de vangodp  
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 10 años, 7 meses
Puntos: 38
Respuesta: duda para sacar factorial de un numero

Si vas a internet y buscas tipos de datos en C encontraras varios lugares que te explican con unas tablillas una especie de "rango" que se permite guardar en cada tipo de datos.

Lo 1º que debes tener claro es que cuando creas una variable, lo que estas haciendo en realidad es reservar un espacio "finito" para guardar datos.

El problema viene que intentas guardar números demasiados "grandes" en un espacio limitado de la memoria.

en esta tabla de aqui: http://2.bp.blogspot.com/_FIPo8hAXPD...2B+enteros.png

...puedes ver claramente que un entero(int) tiene un rango de -2,147,483,648 a 2,147,483,647.

Cuando intentas poner un numero mas grande que 2,147,483,647 veras que que lo que acontece es que te aparece números negativos pero nunca se salen de ese rango comentado previamente.

Representemos de forma gráfica la cosa:
En una punta tengo -2,147,483,648, en medio tengo el cero y en la otra punta tengo 2,147,483,647

Código C:
Ver original
  1. -2,147,483,648................0....................2,147,483,647

si intento pasar de: 2,147,483,648 lo que sucede es que volvemos a empezar.

Código C:
Ver original
  1. *->  -2,147,483,648................0....................2,147,483,648 |----*
  2. |                                                                          |
  3. |                                                                          |
  4. |                                                                          |
  5. *--------------------------------------------------------------------------*

Se parece un bucle.
La prueba es esta:

Código C:
Ver original
  1. #include <stdio.h>
  2.  
  3.  
  4. int main (){
  5.    
  6.     int n = 2147483647;
  7.    
  8.     printf("El limite de un entero es: %d\n\n", n);
  9.    
  10.     n++;
  11.    
  12.     printf("Entramos por la parte negativa: %d\n\n", n );
  13.    
  14.     //si siguimos sumando vamos hacia a cero o sea la "derecha":
  15.     n++;
  16.    
  17.     printf("%d\n\n", n );      
  18.     n++;
  19.    
  20.     printf("%d\n\n", n );    
  21.    
  22.     getchar();
  23.     return 0;
  24. }

La memoria es finita. Al declarar variables la estas "llenando".

Con esas cosas sabemos que:
-La memoria es finita.
-no puedo guardar todo lo que me antoje "HAY UN RANGO" XD
-si me cuelo al pasar por los limites el programa produce errores(BUGS) ya que no va funcionar como deseamos.


¿La solución?
Escoger un tipo de dato mayor, "que me reserve mas memoria", como long, long long, el modificador unsigned que hace que los números negativos estén en la parte positiva. Si no voy a trabajar con negativos puedo decir que los números que se suelen guardar como negativos que se me guarden como positivos junto con la otra mitad, entonces tendría un rango de 0 a 2147483647 * 2 +1.

Marcar una variable con unsigned es como decir que no voy usar espacio para números negativos pero si los necesito para guardar números positivos. Eso hace que la capacidad duplique en los números positivos, puedes comprobar.

En fin cosas que debes saber pero que a lo mejor nadie te lo ha dicho aun XDD

Suerte:
  #3 (permalink)  
Antiguo 15/02/2015, 17:02
lareto
Invitado
 
Mensajes: n/a
Puntos:
Respuesta: duda para sacar factorial de un numero

Cita:
Iniciado por vangodp Ver Mensaje
en esta tabla de aqui: http://2.bp.blogspot.com/_FIPo8hAXPD...2B+enteros.png
...puedes ver claramente que un entero(int) tiene un rango de -2,147,483,648 a 2,147,483,647.
Cuidado con la tablita esa!
Salvo que 1 char es de un Byte, todo lo demás depende de cada compilador (salvo lo que dice sobre el rango de valores del tipo bool, que es absurdo)

Puedes consultar una tabla real en:
http://www.cplusplus.com/reference/climits/
sin pasar por alto la nota:
"* the actual value depends on the particular system and library implementation, but shall reflect the limits of these types in the target platform."

Última edición por lareto; 15/02/2015 a las 17:05 Razón: corrijo, lo que dice del tipo bool
  #4 (permalink)  
Antiguo 15/02/2015, 19:10
Avatar de vangodp  
Fecha de Ingreso: octubre-2013
Mensajes: 934
Antigüedad: 10 años, 7 meses
Puntos: 38
Respuesta: duda para sacar factorial de un numero

Cita:
Iniciado por lareto Ver Mensaje
Cuidado con la tablita esa!
Salvo que 1 char es de un Byte, todo lo demás depende de cada compilador (salvo lo que dice sobre el rango de valores del tipo bool, que es absurdo)

Puedes consultar una tabla real en:
http://www.cplusplus.com/reference/climits/
sin pasar por alto la nota:
"* the actual value depends on the particular system and library implementation, but shall reflect the limits of these types in the target platform."
Bueno... Algo mas que va en el lote. Que se busque el tipo de dato que le vaya mejor y ya lo solucionará.

Suerte
  #5 (permalink)  
Antiguo 17/02/2015, 14:23
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 11 meses
Puntos: 73
Respuesta: duda para sacar factorial de un numero

En efecto, como ya te han comentado, tienes un desbordamiento de enteros. Con enteros de 32 bits puedes llegar a 12! (tanto si es unsigned como si no). Con un entero de 64 bits llegas a 20! (tanto si es unsigned como si no). Con un tipo float de 32 bits llegas a 34!, y con un double, a 170!
  #6 (permalink)  
Antiguo 17/02/2015, 14:26
 
Fecha de Ingreso: junio-2010
Ubicación: Madrid
Mensajes: 620
Antigüedad: 13 años, 11 meses
Puntos: 73
Respuesta: duda para sacar factorial de un numero

En efecto, como ya te han comentado, tienes un desbordamiento de enteros. Con enteros de 32 bits puedes llegar a 12! (tanto si es unsigned como si no). Con un entero de 64 bits llegas a 20! (tanto si es unsigned como si no). Con un tipo float de 32 bits llegas a 34!, y con un double, a 170!. Ten en cuenta que con float y double tendrás pérdida de precisión.

Etiquetas: factorial, int, numero, programa
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 15:44.