Partage
  • Partager sur Facebook
  • Partager sur Twitter

Calculer la factorielle - Langage C

Sujet résolu
8 janvier 2017 à 15:29:34

Salut à tous ;)

Je souhaite créer un code me permettant de calculer la factorielle d'un nombre.
Je me suis inspiré de ce que j'ai pu lire et voir ici :

https://openclassrooms.com/forum/sujet/factorielle-avec-boucle-for-71698

mais mon code ne fonctionne pas. :(

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

int main()
{
    int n;
    int resultat;
    int cpt;

    resultat = 1;

    printf("Insérer un nombre : \n");
    scanf("%i", &n);

    cpt = n;

    if(n==0 || n==1)
        printf("La factorielle de N est : %i",resultat);

    else

         { while(cpt>1)
            resultat = resultat*cpt;
            cpt = cpt-1;

        printf("La factorielle de N est : %i",resultat);
         }

    return 0;
}



Pourriez-vous m'expliquer mes erreurs ?
Ne serait-il pas plus judicieux d'utiliser une boucle for pour gagner en clarté ? 

Merci à vous :D 

-
Edité par Petitevache 8 janvier 2017 à 15:31:29

  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2017 à 15:30:44

Il ne fonctionne pas, c'est-à-dire ? Indique le résultat que tu attendais et le résultat qu'il affiche.

(Mais peut-être que les lignes 23 et 24 devraient être mises dans un même bloc, sans quoi le 'while' de la ligne 22 ne portera que sur la ligne 23, pas sur la ligne 24.)

-
Edité par robun 8 janvier 2017 à 15:34:46

  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2017 à 15:32:49

En fait mon IDE se lance et m'inscrit : Insérer un nombre.
Je saisis un nombre, et quand je fais entrée, il passe à la ligne suivante où là je ne peux rien afficher de plus.

En saisissant 5 (1*2*3*4*5), je souhaiterai que cela m'affiche 120.

-
Edité par Petitevache 8 janvier 2017 à 15:34:40

  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2017 à 15:35:58

Bonjour,

normal, il y a une boucle infinie, tu décrémentes cpt en dehors de la boucle. Indente mieux ton code, essaye d'utiliser le debuger en mode pas à pas pour bien voir ce qui se passe.

-
Edité par PicoDev 8 janvier 2017 à 15:36:30

  • Partager sur Facebook
  • Partager sur Twitter
First solve the problem. Then, write the code. ~ John Johnson
8 janvier 2017 à 15:49:00

Merci pour vos indications ;)

Je crois que j'ai un soucis pour utiliser le pas à pas...

Normalement il faut placer un point d'arrêt, puis utiliser la commande " debug/continue " non ?

J'obtiens un message d'erreur : " Il n'y a pas de disque dur dans le lecteur".
Je vais jeter un oeil sur le net. 

  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2017 à 15:53:20

Je ne connais pas ton ide, mais en gros tu places effectivement un point d'arrêt puis ensuite tu devrais avoir quelque chose comme next pour passer à la ligne suivante, step in pour rentrer dans une fonction, …

Savoir utiliser le debuger est indispensable.

  • Partager sur Facebook
  • Partager sur Twitter
First solve the problem. Then, write the code. ~ John Johnson
8 janvier 2017 à 16:11:47

Salut ! 

Lorsque l'on doit faire une boucle, si tu connais le nombre d'itération, il est préférable d'utiliser une boucle for. Ici, tu sais que tu vas faire n itération ;p

et évite de ne pas mettre d'accolade lorsque tu met un if/else/while/.../  cela évitera que ta décremtentation se retrouve en dehors de ta boucle while alors que tu pensais qu"elle était dedans... 

-
Edité par edouard22 8 janvier 2017 à 16:13:46

  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2017 à 16:31:08

PicoDev a écrit:

Savoir utiliser le debuger est indispensable.

Effectivement ;) :)

edouard22 a écrit:

Salut ! 

Lorsque l'on doit faire une boucle, si tu connais le nombre d'itération, il est préférable d'utiliser une boucle for. Ici, tu sais que tu vas faire n itération ;p

et évite de ne pas mettre d'accolade lorsque tu met un if/else/while/.../  cela évitera que ta décremtentation se retrouve en dehors de ta boucle while alors que tu pensais qu"elle était dedans... 

-
Edité par edouard22 il y a 7 minutes


@Pico. J'utilise Codeblocks. Je chercherai en détai comment ne plus obtenir ce message d'erreur. J'ai regardé le manuel de CodeBlocks et à priori je fais ce qu'il faut...

@Edouard. Ok, merci pour la précision. Si je comprends bien, si je voulais connaitre la factorielle des 10 premiers nombres entiers, à ce moment là l'utilisation d'une boucle for serait appropriée. Comme là je souhaite calculer la factorielle de tous les entiers, la boucle while est plus adapté.

J'avoue avoir du mal à repérer les placements des accolades pour le moment...o_O

Dans le code que j'ai indiqué, il me semblait que ma décrémentation était correctement encadré {}, mais apparemment ce n'est pas le cas:(

Pour le moment, mon mode pas à pas ne fonctionne pas. N'obtennant pas d'erreurs graves lors de la compilation, j'en déduis que j'ai un soucis au niveau des accolades...

Si mon erreur n'est que là, pourriez-vous m'indiquer les bons placements des accolades ?

Merci :D





-
Edité par Petitevache 8 janvier 2017 à 16:31:37

  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2017 à 17:06:33

Bon ce n'est pas compliqué : pour toutes les structures de contrôle (if, while, for, …) tout ce qui est dans la boucle doit être entouré d'accolades. Ron code un peu mieux indenté et corrigé donnerait :

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

int main(void)
{
    int n;
    int resultat;
    int cpt;

    resultat = 1;

    printf("Insérer un nombre : \n");
    scanf("%i", &n);

    cpt = n;

    if(n==0 || n==1)
        printf("La factorielle de N est : %i",resultat);
    else
    {
        while(cpt>1)
        {
            resultat = resultat*cpt;
            cpt = cpt-1;
        }
        printf("La factorielle de N est : %i",resultat);
    }

    return 0;
}


Maintenant à propos de ton «Comme là je souhaite calculer la factorielle de tous les entiers ...», il ne faut pas oublier qu'en C les types de bases sont limités, du coup pour un type comme int, qui est signé, tu as 31 bits (en général) ce qui limite le calcul de la factoriel à 12!. En gros : 32 bits -> 12!, 63/64 bits → 20!, 128 bits → 34!.

  • Partager sur Facebook
  • Partager sur Twitter
First solve the problem. Then, write the code. ~ John Johnson
8 janvier 2017 à 17:59:13

Merci pour votre aide ;)

C'est incroyable la rigueur que ça demande, de bien coder :euh:. Un petit oubli d'accolade et plus rien ne marche ^^

J'ai eu beaucoup de mal à comprendre la logique de la construction de ce code (j'ai l'habitude de réfléchir à l'envers  :diable:)

Dans ma logique, si je voulais trouver le résultat de la factorielle de 5, j'avais besoin uniquement de deux variables : n et cpt
Par ailleurs, j'aurais plutôt utiliser une incrémentation plutôt qu'une décrementation sur mon compteur...


Le résultat final serait apparu par des opérations effectués sur ces deux variables. (c'est possible ? :euh:)

Merci

-
Edité par Petitevache 8 janvier 2017 à 17:59:42

  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2017 à 18:36:00

Petitevache a écrit:

Dans ma logique, si je voulais trouver le résultat de la factorielle de 5, j'avais besoin uniquement de deux variables : n et cpt
Par ailleurs, j'aurais plutôt utiliser une incrémentation plutôt qu'une décrementation sur mon compteur...


Justement, c'est ce qu'on aurait fait en C...

surement un truc comme :

int main(){
    

    int resultat=1;
    int n;
    
    printf("Insérer un nombre : \n");
    scanf("%i", &n);
    
    if(n> 1){
    
        int i;
        for (i = 2 ; i <= n ; i++ ){
            resultat*= i;
        }
    }
    printf("La factorielle de %i est : %i",n,resultat);
    
    return 0;
}

(non testé)

-
Edité par edouard22 8 janvier 2017 à 19:55:39

  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2017 à 19:54:53

En cours de réponse ... ^^

Merci à toi, ça fonctionne :)

Juste une petite erreur ^^

Tu as oublié une accolade à la fin  :lol:

C'est quand même perturbant l'apprentissage du code, car il y a plusieurs solutions qui sont possibles pour un même problème.

C'est dérangeant car l'écriture d'une solution différente m'apparaît parfois diffcilement appréhendableo_O alors que dans l'absolu on parvient au même résultat.

J'ai clairement un niveau novice en langage C, et la lecture de ton code me permet de saisir quelques subtilités.
Par exemple, ligne 4, je ne savais pas que l'on pouvait déclarer et attribuer en même temps, une valeur à une variable.

Perso, j'aurais indiqué int resultat,n;
Et plus loin resultat = 1 

On pourrait par exemple déclarer en variable : int i=2 ; ? 

1)

Ici tu n'as pas traité les cas particuliers, si l'utilisateur rentre 0 ou 1 (l'utilisateur peut être bête parfois ^^ ). Rien de grave en soi ? Est-ce une bonne habitude de traiter en priorité les cas particuliers, ou ce n'est pas forcément nécessaire ?

2)

J'essaye de faire très attention à l'indentation pour prendre de bonnes habitudes. N'aurait-t-il pas été plus clair ( ou habituel ) de placer la ligne 12 après la ligne 5 ?
Par ailleurs, je me rends compte que pour coder un programme traitant les factorielles, il y a toujours besoin d'un minimum de trois variables (n, resultat,i). En décomposant ton code, je comprends mieux à présent pourquoi on ne peut pas se passer de la variable résultat

3) 

J'avoue avoir du mal à comprendre ce qui est mentionné dans la boucle for à la ligne 14.
J'ai lu les chapitres traitant des opérateurs dans C, et je comprends le signe *=.
Si j'ai bien compris, c'est le fait de multiplier deux valeurs et les stocker le résultat dans une variable.
Ici on multiplie resultat par i et le résultat de cette opération est stockée dans la variable résultat ?

Ps : J'insiste peut-être un peu, mais je préfère que cette base soit claire pour moi, avant de m'avancer dans des exercices plus difficiles.

Merci =) 


-
Edité par Petitevache 8 janvier 2017 à 20:10:58

  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2017 à 21:21:49

Petitevache a écrit:

En cours de réponse ... ^^

Merci à toi, ça fonctionne :)

Juste une petite erreur ^^

Tu as oublié une accolade à la fin  :lol:

En fait, j'avais mis une accolade en trop ^^.  


C'est quand même perturbant l'apprentissage du code, car il y a plusieurs solutions qui sont possibles pour un même problème.

C'est dérangeant car l'écriture d'une solution différente m'apparaît parfois diffcilement appréhendableo_O alors que dans l'absolu on parvient au même résultat.

J'ai clairement un niveau novice en langage C, et la lecture de ton code me permet de saisir quelques subtilités.


Par exemple, ligne 4, je ne savais pas que l'on pouvait déclarer et attribuer en même temps, une valeur à une variable.

Perso, j'aurais indiqué int resultat,n;
Et plus loin resultat = 1 

On pourrait par exemple déclarer en variable : int i=2 ; ? 

Content que l'exemple te sois utile. c'est justement ce qui est intéressant en programmation, il n'y a jamais qu'une solution pour répondre à un problème. et il y en as encore beaucoup afin de calculer une factorielle.  déclarer int i=2; ne sert pas car i=2 est exécuté à l'entré de la boucle for. 

mais tu pourrais en effet écrire : 

int i = 2;
for (/* pas d'initialisation*/  ;  i <= n ; ++i ) {



1)

Ici tu n'as pas traité les cas particuliers, si l'utilisateur rentre 0 ou 1 (l'utilisateur peut être bête parfois ^^ ). Rien de grave en soi ? Est-ce une bonne habitude de traiter en priorité les cas particuliers, ou ce n'est pas forcément nécessaire ?

Ce sont deux façon de faire. ici, le code donne le bon résultat même pour n=0 ou 1 puisque le contenu du if n'est pas exécuté et qu'on passe directement au printf lorsque n=0 ou 1 et donc résultat reste égal à 1. 


2)

J'essaye de faire très attention à l'indentation pour prendre de bonnes habitudes. N'aurait-t-il pas été plus clair ( ou habituel ) de placer la ligne 12 après la ligne 5 ?
Par ailleurs, je me rends compte que pour coder un programme traitant les factorielles, il y a toujours besoin d'un minimum de trois variables (n, resultat,i). En décomposant ton code, je comprends mieux à présent pourquoi on ne peut pas se passer de la variable résultat


Non pas forcément. la variable i n'est utile que dans le cas ou n>1, il est donc "justifié" de la déclaré dans le bloc ou n> 1. mais tu aurais aussi pus la déclarer ligne 5.  A vrai dire, on aurait pus se passer de la variable résultat en faisant : 

int fact(int n ) {
    if ( n <= 1) return 1;
    return n*fact(n-1); }
int main(){
     
 
    int n;
     
    printf("Insérer un nombre : \n");
    scanf("%i", &n);
     
    printf("La factorielle de %i est : %i",n,fact(n) );
     
    return 0;
}



3) 

J'avoue avoir du mal à comprendre ce qui est mentionné dans la boucle for à la ligne 14.
J'ai lu les chapitres traitant des opérateurs dans C, et je comprends le signe *=.
Si j'ai bien compris, c'est le fait de multiplier deux valeurs et les stocker le résultat dans une variable.
Ici on multiplie resultat par i et le résultat de cette opération est stockée dans la variable résultat ?

Ps : J'insiste peut-être un peu, mais je préfère que cette base soit claire pour moi, avant de m'avancer dans des exercices plus difficiles.

Merci =) 


-
Edité par Petitevache il y a environ 1 heure

On peut remplacer résultat *= i par resultat= résultat*i ;

edit : j'avais mal lu. la boucle for marche comme sa : 

for( initialisation; condition ; pas )

ici, je fais varier i de 2 à n. et donc, j'ai resultat= 1 * 2 * ... * n 

edit : je suis totalement d'accord avec @PicoDev . 

-
Edité par edouard22 8 janvier 2017 à 21:49:48

  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2017 à 21:41:05

Petitevache a écrit:

C'est quand même perturbant l'apprentissage du code, car il y a plusieurs solutions qui sont possibles pour un même problème.

C'est dérangeant car l'écriture d'une solution différente m'apparaît parfois diffcilement appréhendableo_O alors que dans l'absolu on parvient au même résultat.


Dis toi une chose, la première chose à faire est de ne surtout pas écrire le code, c'est la dernière chose à faire. Pour trouver une solution il vaut mieux prendre un crayon et une feuille de papier, allumer ses neurones et réfléchir. Tu t'acclimates au problème, tu le résous manuellement, tu en tire un algo et seulement une fois que tu es sûr d'avoir quelque chose de correct tu commences à l'implémenter.

Il est intéressant et instructif de toujours regarder sur le net les algos spécifiques pour la résolution des problèmes classiques, tu en apprendras toujours beaucoup car en général le premier jet que tu vas créer sera ce qu'on appelle une version naïve (ce n'est pas péjoratif).

Il y a des algos et structure de données importants à connaître qui vont te fournir la base pour aller plus loin.

  • Partager sur Facebook
  • Partager sur Twitter
First solve the problem. Then, write the code. ~ John Johnson
8 janvier 2017 à 22:18:28

Plus je vous lis, et plus j'ai des questions qui me viennent ^^
C'est vraiment pas évident de se lancer dans l'apprentissage d'un langage web.

Toujours, l'impression d'être plus con que la moyenne, en mettant 3 plombes à comprendre un truc :lol: Ca a été galère pour vous au début aussi ?
Si vous avez des conseils à me donner, je suis preneur ;) Je regarde pas mal de tuto également sur youtube, des fois je comprend mieux certaines choses.

J'avais pensé à acheter un bouquin, mais apparemment c'est le même contenu proposé sur le site...

 https://www.amazon.fr/Apprenez-%C3%A0-programmer-en-C/dp/B010GGJTWM/ref=sr_1_1?ie=UTF8&qid=1483909646&sr=8-1&keywords=langage+c

Sinon pour des exo, j'avais repéré ce livre :

https://www.amazon.fr/Programmer-langage-Cours-exercices-corrig%C3%A9s/dp/2212118252/ref=sr_1_1?ie=UTF8&qid=1483909695&sr=8-1&keywords=langage+c+exercice

int main(){
     
 
    int resultat=1;
    int n;
     
    printf("Insérer un nombre : \n");
    scanf("%i", &n);
     
    if(n> 1){
     
        int i;
        for (i = 2 ; i <= n ; i++ ){
            resultat*= i;
        }
    }
    printf("La factorielle de %i est : %i",n,resultat);
     
    return 0;

Dans ce code, une question au moment de la boucle for.
La seconde expression est la condition d'arrêt. Perso, une erreur de logique que j'ai fais au début (parmi tant d'autres ^^ ), c'était de mettre i = n au lieu de i<=n.

Je croyais que l'ordinateur comprendrait qu'on voulait que i passe par tous les entiers, jusqu'à arriver a n. C'est implicite ^^
Aucun second degré ces ordi :lol:.

En fait, je me rends compte que ta dernière version du code correspond à ce que je voulais faire à mon code au début ! Mais j'étais bloqué car il me manquait des "formules" que je n'ai pas l'habitude de manipuler. Dans un sens ça me rassure, ma façon d'appréhender le problème était viable :magicien:

Tu as raison Pico, pas la peine de se lancer dans l'écriture d'un code si on ne saisit même pas la logique que l'on veut appliquer à notre code.
Souvent quand je fais face à un problème, j'ai tendance a aller complexifier énormément les choses :diable: Quand on décompose à la main ce que l'on souhaite faire, ça apparaît de suite plus simple.

Je vais me lancer dans un exercice pour calculer les puissances d'un nombre.  :ninja:

Ps : Quand je crée un code avec codeblock et que j'enregistre ce code dans un dossier ( placé sur mon bureau ) il m'arrive de ne plus pouvoir supprimer ces codes par la suite ( mon IDE et codeblock étant pourtant fermé... ) Si vous avez une suggestion :o

Merci à vous, c'était très instructif !

  • Partager sur Facebook
  • Partager sur Twitter
8 janvier 2017 à 22:23:47

Petitevache a écrit:

Plus je vous lis, et plus j'ai des questions qui me viennent ^^
C'est vraiment pas évident de se lancer dans l'apprentissage d'un langage web.

Tu ne vas pas te faire que des amis … C n'est pas un «langage web» …

  • Partager sur Facebook
  • Partager sur Twitter
First solve the problem. Then, write the code. ~ John Johnson
8 janvier 2017 à 22:29:58

Oui langage de programmation, mille excuse :ange: 

Dans le dernier code, je fais l'apprentissage qu'on peut se passer d'une boucle pour résoudre ce genre de problème.
Je relirai mes cours, car à force d'entendre parler de boucles, on se dit qu'il en faut partout ^^

Enfin bref, quoi qu'il en soit c'est super passionnant de découvrir tout ça ;) 

  • Partager sur Facebook
  • Partager sur Twitter
12 décembre 2017 à 19:26:07

Bonjour, 

j'aimerai savoir comment faire pour calculer la factorielle de x nombre en language C sur codeblocks

  • Partager sur Facebook
  • Partager sur Twitter
12 décembre 2017 à 20:29:59

Malheureusement, Ce n'est pas possible. TU dois le faire en assembleur avec paint.
  • Partager sur Facebook
  • Partager sur Twitter