Error al hacer la factorial de un numero en C

Iniciado por diegofah, 6 Septiembre 2013, 05:36 AM

0 Miembros y 1 Visitante están viendo este tema.

diegofah

Buenas a todos, este es el primer mensaje que hago ya que recién estoy comenzando en esto de la programación, no se si es muy básica mi pregunta (ya que veo preguntas que no entiendo en el foro), ojala me puedan ayudar, bueno yendo al punto, tengo que hacer un código para hallar el factorial de un número del 1 al 27 y tiene que ser impar positivo sin decimales, todo bien, pero cuando quiero sacar el factorial digamos de 25 no me da el valor correcto (comprobando con la calculador de la PC), no se donde podría estar el problema? ojala me puedan ayudar, y sry si es muy de novato la pregunta, gracias de antemano a todos.

#include<stdio.h>
#include<math.h>
#include<conio.h>
//factorial de un numero dado en rago de 1 a 27
main()
{
int i,x,z;
double P;
float n,y;
printf("\t\tInserte un numero entero impar entre 1 y 27\n\n");
printf("n:");
if (fscanf(stdin,"%f",&n))
 {
 x=n;
 y=n-x;
 if(y==0)
  {
   z=fmod(x,2);
if((x>0) && (x<28))
{
 if(z==1)
      {
       P=1;
       i=1;
       while(i<=n)
        {
         P*=i;
         i++;
        }
        printf("El factorial de n=%1.0f es %1.0f",n,P);
      }
     else printf("no es un numero impar");
}
else printf("no esta dentro el rango");
  }
  else printf("No es un numero entero");
 }
else
 {
  printf("no es un numero\n");
 }
 getch ();
 return 0;
}

eferion

Nota inicial: para dar color al código, la etiqueta code tienes que dejarla así (pero sin espacios): [ code = c ]

  x=n;
  y=n-x;
  if(y==0)
  {


Si x = n entonces y = 0, luego siempre va a entrar en el if. Eso no tiene demasiado sentido, no?

Además la asignación x = n te genera otro problema y es que estás usando el mismo valor en dos variables. Quiero decir, luego no modificas ni n ni x, por lo que te puedes ahorrar el uso de una de las dos variables.

Si lo que quieres es limitar la entrada a números enteros, puedes hacerlo así:


int dato;

// leemos un numero entero
fscanf( stdin, "%d", &dato );

// lo convertimos a float
float n = (float)dato;


Mas cosillas, lo del uso de fmod no lo he terminado de entender. Me explico:


    z=fmod(x,2);
if((x>0) && (x<28))
{
  if(z==1)


La validación del rango de valores ( de 1 a 27 ) debería comprobarse nada más recibir el dato por parte del usuario, no 6 líneas más abajo. Dicho de otra forma, si el usuario introduce un dato incorrecto lo normal es avisarle en ese mismo momento, además el código te quedará más claro.

Si lo que quieres saber es si un número es par o impar tienes opciones mucho más sencillas, rápidas y eficientes:


// Comprobar si el número es par
if ( x % 2 == 0 )

// Comprobar si el número es impar
if ( x % 2 != 0 )


Lo de que te salga mal el resultado ahora no lo puedo mirar porque no puedo compilar tu código ahora. Si tengo tiempo luego y nadie te ha contestado intento ayudarte más.

Un saludo.

ecfisa

Hola diegofah.

Copié tu código y parece dar el resultado correcto.

Pero, según entiendo, si el tipo que estás utilizando para almacenar el resultado del factorial es de 64 bits el máximo valor almacenable es :

2^64  = 18446744073709551616
20!   =  2432902008176640000 (correcto)
21!   = 51090942171709440000 (desborde)



Si fuese de 128 bits:

2^128 = 340282366920938463463374600000000000000
34!   = 295232799039604006218354100000000000000   (correcto)
35!   = 10333147966386100700879664000000000000000 (desborde)


De todos modos, si la especificación del código es que sólo calcule los factoriales de los números impares comprendidos entre 1 y 27, creo que el código se puede simplificar bastante. Por ejemplo:


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

double fact(char);

main()
{
int n;

do {
  printf("Inserte un numero entero impar entre 1 y 27:");
  fscanf(stdin, "%d", &n);
  while(getchar()!='\n');
} while (n<1 || n>28 || n % 2 == 0);

printf("El factorial de %d es %0.0f\n",n, fact(n));

return 0;
}

double fact(char num)
{
double fact = 1;
while (num > 0)
  fact *= num--;
return fact;
}


Saludos :)