Calcul de factorielle en C

bonjour, en tp d’info on doit tapper un programme qui calcul le factorielle d’un nombre entier n e utilisant que les boucle (for , while …) pas de calcul recursif .

le probleme c que mon programme renvoie n’importe quelle valeur par exemple je fais factorielle 4 et ca ma donne -247367142
et je ne trouve pas du tout ce qui coince .

est ce que vous voyez ou est l’erreur ?

merci


#include <stdio.h>
#include <stdlib.h>

int factorielle(int n)
{
int i; /compteur de boucle/
if(n==0)
{
return 1 ;
}
else
{
for(i=1 ; i<=n-1 ; i++)
{
n=n*(n-i);
};
return n;
};
};

int main()
{
int n ;
int reponse;

printf(“entrer n s’il vous plait \n”);
scanf("%i" , &n);

reponse = factorielle(n);

printf("%i factorielle vaut %i \n" , n , reponse);
return 0;
}


int factorielle(int n)
{
int resultat;

    if(n<=0)
    {
     return 1;
    }
    else
    {
     for(resultat =1; n > 1; n--)
     {
        resultat *= n;
     }
    }
  
   return resultat;
}

Pour compléter la réponse de KarLKoX, y’a quelque chose a éviter à tout prix… Dans ta fonction factorielle, je lis le code suivant:

for(i=1; i<=n-1; i++)
{
   n=n*(n-i);
};

Or, tu n’as pas du te rendre compte que ta variable de boucle n était affecté à l’intérieur de la boucle, ce qui te cause à coup sur des erreurs à l’exécution

gaadek : ici n, c’est l’argument passé à la fonction :slight_smile:

Et pour faire mon chieur :

int factorielle(const unsigned int n) {
  if (n < 2) return 1;
  unsigned int result = 1U;
  for (unsigned int i = 2; i <= n; ++i) {
    result *= i;
  }
  return result;
}

(bien sûr, limité à n = 13)

Bonjour, si tu veux tout mettre dans ta seule fonction principale main(), je te fournis le code suivant avec les 2 méthodes (for ou while), élimine celle que tu veux pas…


#include<stdio.h>
main()
{
      int i,n,fact;
      
      printf("Entrer n : ");
      scanf("%d",&n);
      
      /* boucle for */
      for(i=1,fact=1;i<n+1;i++)
      fact*=i;
      printf("%d!=%d",n,fact); 
      
      printf("\n\n");
      
      /* boucle while */
      i=1;
      fact=1;
      while(i<n+1)
      {
          fact*=i;
          i++;
      }
      printf("%d!=%d",n,fact);
      
      return 0;
}

Heuu, j’ai un gros doute là d’un coup…

imaginons la fonction suivante:

int test (int n)
{
  int i;

  for (i=0; i<n; i++)
    n = i++;

  return n;
}

Bah franchement, je ne suis pas sur de pouvoir certifier que la fonction pourra s’exécuter correctement

Au temps pour moi, j’ai lu de travers entre affecté et déclarée.

(par contre ton exemple ne risque pas trop de foirer, n = i++ => n = 0, et de facto i < n => 2 < 0)

super merci beaucoup , personnelement j’aurais jamais vu l’erreur , c’est vraimmment le genre d’erreur qui passe vraimment inapercu et que tu ne remarque pas . merci encore c’est genial :smiley:

#include <stdio.h>
#include <stdlib.h>

int factorielle(int n)
{
int i; /compteur de boucle/
int maxi ;
maxi = n-1 ;
if(n==0)
{
return 1 ;
}
else
{
for(i=1 ; i<=maxi ; i++)
{
n=n*(n-i);
};
return n;
};
};

int main()
{
int n ;
int reponse;

printf(“entrer n s’il vous plait \n”);
scanf("%i" , &n);

reponse = factorielle(n);

printf("%i factorielle vaut %i \n" , n , reponse);
return 0;
}

bo alors j’ai crée une nouvelle variable dans la fonction . seleument maintenant

pour n = 0 ca donne 1
pour n = 1 ca donne 1
pour n = 2 ca donne 2
et …

pour n = 3 ca donne … 24
et pour n = 4 c’est le bouquet … 14040 ! :paf:

Je crois que c’est seulement le return qui est mauvais :ane:

Je me suis juste permis d’“améliorer” un peu:

#include <stdio.h>
#include <stdlib.h>


int factorielle(int n)
{
    int i; /*compteur de boucle*/
    int valeur = 1; 

    if(n==0)
        return 1;
    else
        for(i= 1; i <= n; i++)
            valeur *= i;

    return valeur;
};



int main()
{
    int n, reponse;

    printf("entrer n s'il vous plait \n");
    scanf("%i" , &n);

    reponse = factorielle(n);

    printf("%i factorielle vaut %i \n" , n , reponse);
    system("PAUSE");
    return 0;
}

Edité le 13/01/2012 à 18:19

ca veut dire quoi "valeur*= i " il fait quoi l’operateur *=

merci

Ha ouai excuse moi. En faite, le C a des sortes de raccourcis très agréables (que certains trouve illisible).

valeur* = i

correspond à

valeur = valeur * i

Et sinon, un conseil: essaye d’utiliser la balise CODE afin de rendre ton code plus lisible.

EDIT: j’t’ai eu :paf:

Cela permet de raccourcir l’écriture
valeur *= i est équivalent à valeur = valeur * i

edit : grillaid :paf:

merci pour votre aide ! et bonne journée

Dans la fonction int factorielle(int) de Dusty, on pourrait modifier 2/3 trucs

int factorielle(unsigned int n) { //FIX: changement de type pour "unsigned int"
    int i; /*compteur de boucle*/
    int valeur = 1;
    if(n == 0 || n == 1) { //EVOL: Gestion du cas particulier "1!"
        return 1;
    }
    else {
        for(i= 1; i <= n; i++) {
            valeur *= i;
        }
    }
    return valeur;
};

Notez qu’il y a peut-être quelques fautes de syntaxe : cela fait longtemps que je n’ai plus fait de C [spoiler]Le Java c’est mieux[/spoiler]

Bien vu, pas de factorielle sur un nombre négatif.

Et juste pour me la ramener :ane:

Je modifierais

n == 0 || n == 1

En

n <= 1

Je trouve que c’est un peu plus lisible (mais j’imagine que c’est peut-être un peu personnel).

Et je supprimerais toutes les accolades qui servent à rien (celles du if et du for). J’aime bien les supprimer parce que je trouve le code plus “aérien”.

Bon, peut-être encore quelques-unes modifs et on va sans doute atteindre la perfection. Il faudrait presque proposer le code à Linus pour le mettre dans son noyau (ne me dites par pourquoi, je sais pas :paf: )

Je vous promets, c’est le dernier code que j’écris :pt1cable: . Je pense que celui là est plus rapide que les précédents (mais utilise plus de mémoire…)

#include <stdio.h>
#include <stdlib.h>

const unsigned int valfct[] = {1, 1, 2, 6, 24, 120, 720, 5040,
                                            40320, 362880, 3628800,
                                            39916800, 479001600};

unsigned int factorielle(unsigned int n)
{
     return n > 12 ? 0 : valfct[n];
}

int main()
{
     printf("Factorielle de 5: %u\n", factorielle(5));
     return 0;
}

En effet, c’est en voulant faire cette optimisation que je me suis rendu compte que la fonction acceptait des entiers négatifs, j’ai donc mis “n == 0 || n == 1”. Ce n’est que après que je me suis rappelé que n! n’existait que pour des positifs, j’ai donc corrigé le type de n, mais j’ai oublié d’adapter le if() :riva:[quote=“Dusty”]
Et je supprimerais toutes les accolades qui servent à rien (celles du if et du for). J’aime bien les supprimer parce que je trouve le code plus “aérien”.
[/quote]
Là c’est juste une habitude, personnellement, j’aime pas ne pas voir les accolade car je trouve qu’on discerne moins les blocs/briques de code (et donc les différents branchements). :o
Mais comme on dit : “Les goûts et les couleurs…:slight_smile:

Et si l’utilisateur entre un nombre négatif, ça plante, et si tu veux calculer factorielle 16, ça renvoie 0, ce qui n’est pas le cas… Bref, solution à éviter absolument

Oui et non. 13! = 6227020800 >> 2^32-1

Donc au final : vérifier les bornes :
assert(n<=sizeof(valfct)/sizeof(unsigned int);
if (n <= 1) return 1;

etc :slight_smile:

(bon bien sûr, à revoir sur du 64bits… mais même si c’est généralisé côté proc, c’est pas forcément le cas OS (je parle pas de Linux, mais de Win…))