2009-05-09 4 views
0

Je n'arrive pas à faire fonctionner le code suivant.Impossible d'obtenir une fonction factorielle pour travailler dans C

#include <stdio.h> 

// I am not sure whethere I should void here or not. 
int main() { 
    // when the first bug is solved, I put here arg[0]. It should be 
    // similar command line parameter as args[0] in Java. 
    int a=3;     
    int b; 
    b = factorial(a); 

    // bug seems to be here, since the %1i seems to work only in fprintf 
    printf("%1i", b); 
    return 0;  
} 

int factorial(int x) { 
    int i; 
    for(i=1; i<x; i++) 
     x *= i; 
    return x; 
} 

Comment pouvez-vous obtenir le code de travailler?

Répondre

9

AInitak a donné la bonne réponse, mais je veux ajouter que d'une façon que vous pouvez trouver le bug dans votre code est d'imprimer les valeurs de i et x dans la boucle factoriel.

int factorial(int x) { 
    int i; 
    for(i=1; i<x; i++) 
    { 
     x *= i; 
     printf("%d, %d\n", i, x); 
    } 
    return x; 
} 

Cela vous donne la sortie

1, 3 
2, 6 
3, 18 
4, 72 
5, 360 
6, 2160 
7, 15120 
8, 120960 
9, 1088640 
10, 10886400 
11, 119750400 
12, 1437004800 
13, 1501193216 
14, -458131456 
-458131456 

Cela rend plus facile de voir ce qui se passe mal. La boucle ne s'arrête pas là où vous l'attendez pour les raisons expliquées par AInitak.

1

Quel message d'erreur obtenez-vous?

Tout d'abord, déclarez votre fonction factorialavantmain. Aussi, faites attention à corriger l'indentation. Votre déclaration de la fonction main est correcte, soit dit en passant.

+0

Pas dans C; il devrait avoir un "vide". Voir la réponse de litb. –

+0

@Merci de montrer la convention que je n'ai pas suivie. Mon erreur "message" était que j'ai un trop grand nombre négatif. –

+0

Que dois-je corriger dans mon indentation pour l'obtenir plus C-like? –

15

Vous modifiez votre variable de fin de boucle (x) à l'intérieur de la boucle. Actuellement votre code explose après quelques itérations, quand x dépasse la plage d'un entier de 32 bits et devient alors négatif et très grand, terminant ainsi la boucle.

Il devrait être:

int factorial(int n) { 
    int i, x = 1; 
    for (i = 2; i <= n; ++i) { 
     x *= i; 
    } 
    return x; 
} 

Mieux encore, vous devez utiliser long au lieu de int pour la variable x et la valeur de retour, parce que n! devient très grand très rapidement.

+0

J'ai changé int en longs. Je reçois le message d'erreur suivant: http://dpaste.com/42442/. J'ai apparemment besoin d'une bibliothèque. –

+0

vous avez changé trop d'ints. Le retour de main devrait toujours être un int. – Alnitak

1

Je suggère d'utiliser également le calcul factoriel double ou non signé afin de pouvoir calculer la plus grande valeur de la fonction factorielle.

double fact(double n) 
{ 
    if (n == 1) 
     return 1; 
    return n*(fact(n-1)); 
} 
3

Il est mauvais style C à laisser de void lors de la définition ou la déclaration d'une fonction. Donc, mettez-le dans

int main(void) 

Bien qu'il ne change rien sur le nombre de paramètres de la fonction a (la fonction a zéro des paramètres sans que void soit), il déclarera la fonction qui accepte seulement zéro arguments , alors qu'il ne dira rien sur le nombre et les types d'arguments acceptés lorsque vous omettez le void. Cependant, les deux versions avec et sans void sont correctes.

Lisez à ce propos aussi this answer.

+0

@Merci de le signaler! :) –

+0

@litb: Il semble que C est comme Python. Supposons que j'utilise la convention "Explicit is better than implicit". Suis-je mieux avec C en C que sans? –

+0

Oui, je pense que cette règle est généralement bonne. Il y a des cas où j'utiliserais des choses implicites: Comme convertir d'un void * à autre chose, si le résultat est le même de toute façon, ou convertir d'int en long (mais pas l'inverse). Dans ce cas particulier, le vide manquant aura un résultat différent (ne donnera pas un prototype à la fonction - donc aucun des arguments ne peut être vérifié par type et on ne sait pas combien d'arguments sont attendus). Donc, dans ce cas, toujours aller avec "vide". –

2
#include<stdio.h> 

#include<stdlib.h> 

int main(int c,char *v[]) 

{ 

    int x,y; 

    int *num; 

    if(c==1) 

    { 

    printf("Usage : programName : number"); 

    return 0; 

    } 

    num=(int *)malloc(sizeof(int)); 

    *num=atoi(v[1]); 

    x=1;y=1; 

    while(x<=*num) 

    { 

    y=y*x; 

    x++; 

    } 

    printf("Factorial of %d is %d ",*num,y); 

    free(num); 

    return 0; 

} 
+0

Exemple de sortie? –

+1

sortie: factorielle: 5 factorielle de 5 est 120 – Priyanka

1

Une fonction non-récursive plus élégante.

#include<stdio.h> 
long long int fact(long long int); 

long long int fact(long long int n){ 
    long long int num = 1; 
    long long int fi = 0; 
    for(long long int i=2;i<=n;i++){ 
     for(long long int j=1;j<=i;j++){ 
      fi += num;  
     } 
     num = fi; 
     fi = 0; 
    }  
return num; 
}  
int main(){ 
    long long int n; 
    scanf("%lld",&n); 
    printf("%lld\n",fact(n)); 
return 0; 
} 
+0

Pouvez-vous comparer votre proposition à celle de BillTheLizard, s'il vous plaît. http://stackoverflow.com/a/843221/54964 Alors, pourquoi votre proposition est-elle meilleure que la sienne? Quel est le but de 'long long int'? –

Questions connexes