addtion

addtion - C - Programmation

Marsh Posté le 31-01-2007 à 14:41:57    

bonjour,
pour m'amuser j'ai fais un programme ,qui calcule la suite de fibonnaci,dont voici le code :

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main(void)
  4. {
  5.   int limite,i;
  6.   int *fibo,*temp; //initialisation des pointeurs
  7.   char tampon[16]; //tampon pour capture au clavier --> 16 caractères max
  8.   printf("Combien d'iteration ? :" );
  9.   fgets(tampon, 16, stdin); //on envoie l'entrée standard (stdin) dans le tampon
  10.   sscanf(tampon, "%d", &limite); //on lit la valeur du tampon que l'on stocke dans limite
  11.   fibo     = calloc(2, sizeof(int)); //on alloue de la memoire pour un array de 2 entier
  12.   //printf("memoire allouee : %d octet\n",(2 * sizeof(int)));
  13.   fibo[0]  =1;
  14.   fibo[1]  =1;
  15.   printf("%d; iteration 0\n%d; iteration 1\n",fibo[0],fibo[1]);
  16.   for(i=2;i<limite;i++)
  17.    {
  18.     //printf("reallocation de memoire : %d octet\n",(i * sizeof(int)));
  19.     temp    = realloc(fibo, (i+1) * sizeof(int)); //on tente d'ajouter une case au tableau ...
  20.     if(temp == NULL) {printf("erreur de realloctaion de memoire" );} //ça rate ----> exit
  21.     else {temp=fibo;}                                               //ça réussi ---> on continue !!
  22.     fibo = fibo[i-1] + fibo[i-2]; //le coeur du programme !!!!
  23.     printf("fibo[i]= %d+%d=%d; iteration %d \n",fibo[i-1],fibo[i-2],fibo[i],i);
  24.     //if(fibo[i]>limite) break; //si le nombre trouvé est > ou =à la limite on stop
  25.    }
  26.   printf("memoire allouee : %d octet\n",(i * sizeof(int)));
  27.   free(fibo); //on libère la memoire
  28. }
 

sauf que à la 44ème boucle, le programme ne sais plus faire une addition !! il me sort un résultat négatif alors que les deux termes sont positifs ! puis alterne positif/négatif comme bon lui semble :pt1cable: donc j'ai remplacé tous les [i]int par des unsigned int que j'ai remplacer par des long puis par des unsigned long.
je ne vois pas dutout d'où vient ce problème !!
merci d'avance :jap:

Message cité 1 fois
Message édité par nicodu95 le 31-01-2007 à 14:54:18
Reply

Marsh Posté le 31-01-2007 à 14:41:57   

Reply

Marsh Posté le 31-01-2007 à 15:01:53    

Salut,
 

Code :
  1. temp    = realloc(fibo, (i+1) * sizeof(int)); //on tente d'ajouter une case au tableau ...
  2.     if(temp == NULL) {printf("erreur de realloctaion de memoire" );} //ça rate ----> exit
  3.     else {temp=fibo;}


 
Ca serait pas plutôt fibo=temp ?
 
Sinon, je pense que c'est bien un dépassement de capacité sachant que int = long sous système 32 bits et qu'on ne peut pas additionner des nombres indéfiniment.


Message édité par anordem le 31-01-2007 à 15:03:40
Reply

Marsh Posté le 31-01-2007 à 15:13:55    

2^32 = 4 294 967 296 alors que le résultat de l'opération demandé boucle 44 (où ça bug) est
1836311903 +1134903170 = 2 971 215 073  :heink:

 

edit : même une calculatrice sait le faire :o

Message cité 1 fois
Message édité par nicodu95 le 31-01-2007 à 15:20:03
Reply

Marsh Posté le 31-01-2007 à 15:29:24    

ouais, mais 2^31=2 147 483 648
 
Donc pour peu que tu sois en signed long, ça passe plus.
 
Pour faire le test, essaie de voir ce que donne 2^32 + (le nombre négatif que tu obtiens)


---------------
TriScale innov
Reply

Marsh Posté le 31-01-2007 à 17:07:21    

Exact, et vu que le printf affiche des valeurs signées :

Code :
  1. printf("fibo= %d+%d=%d; iteration %d \n",fibo[i-1],fibo[i-2],fibo[i],i);


On obtient des valeurs négatives. Mais bon afficher des entiers non signés ne changent pas grand chose et on doit gagner une itération supplémentaire avant le débordement :
 
fibo= 1836311903+1134903170=2971215073;
fibo= 2971215073+1836311903=512559680;
 
Edit:
 

nicodu95 a écrit :

2^32 = 4 294 967 296 alors que le résultat de l'opération demandé boucle 44 (où ça bug) est  
1836311903 +1134903170 = 2 971 215 073  :heink:  
 
edit : même une calculatrice sait le faire :o


Ah, j'avais pas capté que c'est toi qui a créé le topic. Sympa ta façon de remercier ceux qui prennent la peine de répondre à tes questions...


Message édité par anordem le 31-01-2007 à 17:12:01
Reply

Marsh Posté le 31-01-2007 à 17:12:58    

dans mon printf j'ai remplacé le %d par %u et plus de problème  :jap:

Citation :

Ah, j'avais pas capté que c'est toi qui a créé le topic. Sympa ta façon de remercier ceux qui prennent la peine de répondre à tes questions...


si c'est à ça que tu répond (anordem) :

Citation :

edit : même une calculatrice sait le faire :o

sache que je voulais juste dire que comme une calculatrice sait le faire , sa serait étrange qu'un ordinateur ne le puisse pas  :)

 

merci à tous pour votre aide  :jap:  :jap:   :)

Message cité 1 fois
Message édité par nicodu95 le 31-01-2007 à 17:17:35
Reply

Marsh Posté le 31-01-2007 à 17:25:48    

nicodu95 a écrit :

dans mon printf j'ai remplacé le %d par %u et plus de problème  :jap:


 
Permet moi d'en douter. Tu as simplement supprimer le signe négatif mais tes valeurs sont fausses car
2.971.215.073 + 1.836.311.903 = 4.807.526.976 et pas 512.559.680
 
 
PS : l'humilité ne tue pas et être débutant n'est pas une tare.

Reply

Marsh Posté le 31-01-2007 à 19:40:01    

effectivement , tu as raison , le max que je peux faire est 44 boucle :(  

Reply

Marsh Posté le 31-01-2007 à 22:05:13    

nicodu95 a écrit :

effectivement , tu as raison , le max que je peux faire est 44 boucle :(


 
Utilises des "double" => tu passeras de 4 octets à 8. Et si ton compilo l'accepte, tente le "long double" et t'auras 10 octets pour t'amuser (de quoi aller probablement jusqu'à 50 boucles...)
 
Au fait, pourquoi tu fais un calloc de 2 puis du realloc à chaque boucle ? Tu pourrais pas faire directement un calloc de "limite" ??? Et d'ailleurs, pourquoi "calloc" alors que les seules valeurs que t'as besoin d'initialiser sont "fibo[0]" et "fibo[1]" ???
Fais donc un simple malloc !!!!

Message cité 1 fois
Message édité par Sve@r le 31-01-2007 à 22:09:09

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 31-01-2007 à 22:46:19    

Sve@r a écrit :

Utilises des "double" => tu passeras de 4 octets à 8. Et si ton compilo l'accepte, tente le "long double" et t'auras 10 octets pour t'amuser (de quoi aller probablement jusqu'à 50 boucles...)


Sauf que c'est des flottants...
Par contre en C99 y'a les long long (et sur la plupart des compilos pas-c99 y'a des __int64 qui trainent ou des trucs du genre)


---------------
Me: Django Localization, Yogo Puzzle, Chrome Grapher, C++ Signals, Brainf*ck.
Reply

Marsh Posté le 31-01-2007 à 22:46:19   

Reply

Marsh Posté le 31-01-2007 à 23:07:26    

Mouais, enfin, toutes ces bidouilles ne résolvent pas vraiment le problème. :)
Une méthode plus élégante serait d'utiliser une biliothèque de BigNums, telle que Miracl par exemple http://www.shamus.ie/  

Reply

Marsh Posté le 01-02-2007 à 16:03:51    

0x90 a écrit :

Sauf que c'est des flottants...


Ben t'as quand-même le droit d'additionner des flottants, même si leur partie décimale est toujours à 0...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 10-02-2007 à 12:34:56    

nicodu95 a écrit :

Code :
  1. else {temp=fibo;}



a l'envers, ça tue...
Essaye ça
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4. #ifdef WIN32
  5. #define LLU "I64u"
  6. #else
  7. #define LLU "llu"
  8. #endif
  9. int main (void)
  10. {
  11.    for (;;)
  12.    {
  13.       char tampon[8];           //tampon pour capture au clavier --> 16 caractères max
  14.       printf ("Combien d'iteration ? (ou 'q' pour quitter) :" );
  15.       fflush (stdout);
  16.       fgets (tampon, sizeof tampon, stdin); //on envoie l'entrée standard (stdin) dans le tampon
  17.       {
  18.          int iter;
  19.          int n = sscanf (tampon, "%d", &iter);
  20.          printf("n=%d\n", n);
  21.          if (n == 1) //on lit la valeur du tampon que l'on stocke dans limite
  22.          {
  23.             //on alloue de la memoire pour un array de 2 + iter entier
  24.             unsigned long long *fibo = malloc ((2 + iter) * sizeof *fibo);
  25.             if (fibo != NULL)
  26.             {
  27.                //printf("memoire allouee : %d octet\n",(2 * sizeof(int)));
  28.                fibo[0] = 1;
  29.                fibo[1] = 1;
  30.                printf ("%" LLU "; iteration 0\n"
  31.                        "%" LLU "; iteration 1\n", fibo[0], fibo[1]);
  32.                {
  33.                   int i;
  34.                   for (i = 2; i < iter; i++)
  35.                   {
  36.                      assert (i - 2 >= 0);
  37.                      assert (i < iter);
  38.                      fibo[i] = fibo[i - 1] + fibo[i - 2]; //le coeur du programme !!!!
  39.                      printf ("fibo[i]= %" LLU "+%" LLU "=%" LLU
  40.                              "; iteration %d \n", fibo[i - 1], fibo[i - 2],
  41.                              fibo[i], i + 1);
  42.                   }
  43.                }
  44.                free (fibo), fibo = NULL; //on libère la memoire
  45.             }
  46.             else
  47.             {
  48.                puts ("memory error" );
  49.             }
  50.             assert (fibo == NULL);
  51.          }
  52.          else
  53.          {
  54.             puts ("input error : bye" );
  55.             break;
  56.          }
  57.       }
  58.    }
  59.    return 0;
  60. }

Message cité 1 fois
Message édité par Emmanuel Delahaye le 10-02-2007 à 13:09:59

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 11-02-2007 à 12:55:37    

Emmanuel Delahaye a écrit :

Code :
  1. char tampon[8];           //tampon pour capture au clavier --> 16 caractères max



Faire rentrer 16 caractères (plus le '\0') dans un char[8]... Alors là, je pige que dalle sauf s'il sagit d'une erreur d'inattention comme ça arrive à tous => il n'y a pas longtemps, je voulais calculer la longueur d'une chaîne et rajouter 1 au résultat. Et j'ai tapé

Code :
  1. i=strlen(chaine + 1)

et j'ai galéré au-moins un quart d'heure à essayer de comprendre pourquoi mon programme plantait !!!  :sol:  
 
Sinon je ne trouve pas dans l'algo le test sur "q" pour quitter. Apparemment si on tape "q" (ou toute autre lettre), alors sscanf renverra 0 et il sortira sur le "input error : bye" non ???

Message cité 1 fois
Message édité par Sve@r le 11-02-2007 à 13:07:59

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 11-02-2007 à 15:18:58    

Sve@r a écrit :

Faire rentrer 16 caractères (plus le '\0') dans un char[8]... Alors là, je pige que dalle sauf s'il sagit d'une erreur d'inattention comme ça arrive à tous


 
Bah, j'ai réduit la taille du tableau sans modifier le commentaire. Shame on me...
 

Citation :


Sinon je ne trouve pas dans l'algo le test sur "q" pour quitter. Apparemment si on tape "q" (ou toute autre lettre), alors sscanf renverra 0 et il sortira sur le "input error : bye" non ???

Oui, je n'ai pas dit que seul 'q' permettait de sortir. Ne pas confondre l'absence de spèc avec l'aide à utilisateur !


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed