addition de nombres stocké sous forme de char
Répondre à la discussion
Page 1 sur 2 1 DernièreDernière
Affichage des résultats 1 à 30 sur 59

addition de nombres stocké sous forme de char



  1. #1
    physiquantique

    addition de nombres stocké sous forme de char


    ------

    Bonjour ,
    je me suis lancé dans le c (oui je sais) il y a peu . J'essaye donc réécrire des fonctions que j'avais écrites en vb.net .
    Par exemple , je voudrais pouvoir additionner deux nombres contenues dans des chaines de caractères . Voici mon pauvre code :
    Code:
    char a[] = "123456" , b[]="222" ;
    int itemp =0;
    int retenue=0;
    int tempa;
    int tempb;
    int lena;
    int lenb;
    int main()
    {
      lena =(int)strlen(a);
      lenb=(int)strlen(b);
      
      char result[lena];
      int i=0;
      while (i<=lenb)
        {
          tempa=(int)a[i]; 
          tempb=(int)b[i];
          itemp=tempa+tempb+retenue;
          if (itemp>9)
    	{
    	  retenue=1;
    	  itemp=itemp-10;
    	  printf("chiffre  %d \n\n",itemp);
    	  result[i]=(char)itemp;
    	  
    	}
          else
    	{
    	  retenue=0;
    	  result[i]=(char)itemp;
    	  printf("chiffre :  %d \n\n",itemp);  
    	  
    	}
    
          i=i+1;
        }
      printf("%s \n",result);
    
    }
    Sauf qu'à la compilation , j'ai pleins de warning :incompaptible implicit declaration of built-in function printf.
    Et à l'éxécution , mes printf m'affichent pas du tout le résultat que je comptais (des nombres qui ressemblent à des codes de caractères) .
    Il faut dire que je sais pas trop comment "lire" des nombres stockés sous forme de char ...

    Si quelqu'un avait la gentillesse de me guider.
    Merci d'avance

    Bon week end .

    PS : ya pas une sorte de emacs intégré au forum qui permet de mettre en forme les codes ?

    -----
    Dernière modification par physiquantique ; 18/10/2014 à 13h58.
    vivons avec légerté

  2. #2
    Chanur

    Re : addition de nombres stocké sous forme de char

    Bonjour,

    D'abord ton warning : il signale que tu n'as pas défini la fonction "printf". Pour le faire, il suffit d'inclure le fichier stdio.h (standard input/output) au début de ton programme par la ligne :
    Code:
    #include <stdio.h>

    Ensuite, pour connaître la valeur numérique d'un caractère représentant un chiffre, il suffit de savoir que les codes ASCII des chiffres se suivent, dans l'ordre. Il suffit donc de soustraire le code ASCII de 0 :
    Code:
    valeur_numerique = caractere - '0';
    Ne pas oublier les ' qui encadrent le 0, et se méfier du cas où on aurait un caractère qui ne soit PAS un chiffre.


    Enfin, c'est un exercice intéressant, mais dans une véritable application, on aurait tout intérêt à utiliser les fonctions existantes. Par exemple atoi(chaine_de_caractère) retourne la valeur numérique de la chaîne sous la forme d'un int (exactement du début de la chaîne, jusqu'au premier caractère qui ne soit pas un chiffre).
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

  3. #3
    physiquantique

    Re : addition de nombres stocké sous forme de char

    Merci pour la réponse .
    Quelle librairie faut il importer pour "atoi" ?

    PS: J'éspère que personne remarquera que je ne sais plus faire une addition puisque je part de la gauche vers la droite ...
    vivons avec légerté

  4. #4
    Chanur

    Re : addition de nombres stocké sous forme de char

    Aucune. C'est dans la bibliothèque standard.
    Le prototype est dans stdlib.h
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

  5. A voir en vidéo sur Futura
  6. #5
    physiquantique

    Re : addition de nombres stocké sous forme de char

    Bonjour ,
    Je bute toujours .
    J'ai avancé un peu le code , mais là quand j'exécute , soit le résultat affiché contient le bon nombre , suivi de caractères bizzares (qui semblent venir tout droit de ce qu'il y a de stocké à un certain endroit de la mémoire , mais qui en l'occurence me cassent un peu les pieds) , soit , lorsque j'additionne des grands nombres , le résultat est faux et les caractères bizzares sont toujours là .
    Par exemple : 09999 '@ pour a="99999999" et b ="1" , ou encore : 1000� pour a="999" et b="1" .

    J'ai l'impression que ça vient de la manipulation des chaines de caractères (peut être au niveau des longueurs) .
    Si quelqu'un décèle des erreurs , je l'en remercie beaucoup .
    Code:
    /* ADDITION NOMBRE ARBITRAIREMENT GRANDS */
    /* Un jour de pluie */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void zeros(char a[],int n);
    
    int main()
    {
      char a[] = "999" ; /* Nombres pour tester*/
      char b[]="01" ;
      int itemp =0;
      int retenue=0;
      int tempa,tempb,lena,lenb;
      lena =(int)strlen(a);        /*Longueurs des deux nombres*/
      lenb=(int)strlen(b);
      if (lena >lenb)    /*On égalise les longueurs (comme chez le coiffeur)*/
        {
          zeros(b,lena-lenb); 
        }  
      else
        {
          zeros(a,lenb-lena);
        }
      char result[strlen(b)]; 
      int i=(int)strlen(b)-1; /* Initialisation de i*/
      printf("longueur : %d \n",i);
      while (i>=0)
        {
          tempa=a[i]-'0';            /* On lit le ieme chiffre*/
          printf("lecutre a : %d\n",tempa);
          tempb=b[i]-'0';
          printf("lecutre  b: %d\n",tempb);
          itemp=tempa+tempb+retenue; /*chiffre de a + chiffre de b +retenue*/
          if (itemp>9)
    	{
    	  retenue=1;
    	  itemp=itemp-10;
    	  printf("chiffre[%d] %d \n",i+1,itemp);
    	  result[i+1]=itemp+'0';
    	}
          else
    	{
    	  retenue=0;
    	  result[i+1]=itemp+'0';
    	  printf("chiffre[%d] :  %d \n",i+1,itemp);   
    	}
    
          i=i-1;
        }
    
      /* Si la retenue n'est pas nulle après la boucle*/
      if (retenue!=0)
        {
          result[0]='1';
          printf("chiffre[0] = 1\n");
        }
      else
        {
          result[0]='0';
      }
      result[strlen(result)]='\0';
      printf("%s \n",result);
    }
    Code:
    /* fonction qui ajoute n zeros en début de nombre (le coiffeur)*/
    void zeros(char nombre[],int n)
    {
      int i=0;
      int len=(int)strlen(nombre);
      char c[len+n];
      char d[n];
      char temp[1];
      while (i<n)
        {
          c[i]='0';
          d[i]='0';
          i=i+1;
        }
      i=0;
      strcat(c,nombre);
      strcat(nombre,d);
      strcpy(nombre,c);
      printf("zeros : arg :%s \n",nombre);
    }

    Merci d'avance
    Bonne journée.
    vivons avec légerté

  7. #6
    Chanur

    Re : addition de nombres stocké sous forme de char

    La ligne
    Code:
    result[strlen(result)]='\0';
    est absurde.
    strlen retourne le nombre d'octets non nuls à partir de l'adresse donnée.
    en faisant result[strlen(result)]='\0', on met 0 au premier caractère qui contient 0. Ca ne fait rien du tout.

    Une solution pas fatigante (mais pas optimale) consiste à remplir result de 0 juste après l'avoir alloué.

    D'autre part, tu a alloué result à la longueur de ta plus longue chaîne, mais le résultat peut faire un caractère de plus (ex: 5+5=10) et il faut encore ajouter un caractère pour y mettre le 0 final.
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

  8. #7
    physiquantique

    Re : addition de nombres stocké sous forme de char

    Exact!

    Donc j'enlève le "result[str(result)]='\0'" , et d'autres part je déclare char result[strlen(b)+1] (comme je l'avais fait auparavant) .
    Par contre à l'exécution , le résultat contient le résultat attendu , mais également des caractères bizzarres qui deumeurent .

    Même en initialisant result :
    Code:
    for (i=0;i<strlen(b)+1;i++)
    {
    result[i]='0';
    }
    résultat de 999+1 : 1000�
    résultat de 166+24 : 0190�
    résultat de 16666666+244444 : incohérent (0) (quand j'affiche a[i] et b[i] avec les printf , je trouve du -48 -47 ,... je ne comprends pas. Je pense que la fonction zeros est responsable ) .
    Toujours les deux derniers mêmes caractères en fin de résultat .

    J'ai du mal avec les chaines de caractères...
    Dernière modification par physiquantique ; 09/11/2014 à 09h09.
    vivons avec légerté

  9. #8
    physiquantique

    Re : addition de nombres stocké sous forme de char

    La fonction zeros est mal écrite je pense .
    Je voudrais ajouter n zeros en début de nombre .
    Je crée d de taille n , qui vaut "00...0" . Je concatène nombre à d .
    Et après je voudrais dire "nombre = d" . Mais apparement je sais pas le dire correctement .

    J'avais essayé :

    Code:
     while (i<strlen(nombre)+n)
        {
          if (i<strlen(nombre))
    	{
    	  nombre[i]=d[i];
    	}
          else
    	{
    	  temp[0]=d[i];
    	  strcat(nombre,temp);
    	}
          i=i+1;
        }
    Mais toujours pas le bon résultat .
    Dernière modification par physiquantique ; 09/11/2014 à 09h21.
    vivons avec légerté

  10. #9
    Jack
    Modérateur

    Re : addition de nombres stocké sous forme de char

    Une chose m'échappe:
    tu dis que la fonction zero ajoute des 0 en tête de la chaine. Le problème, c'est que tu travailles avec des chaines statiques, donc de taille fixe. Il est donc interdit d'augmenter le nombre de caractères contenus dans la chaine.
    Il faudra donc définir une taille de tableau correspondant au nombre maxi de chiffre des nombre que tu veux additionner. Si le nombre de caractères ne doit pas être limité, il faudra créer des tableaux dynamiques.

    Un exemple avec des chaines de 10 chiffres pour transformer 133 en 0000000133:
    Code:
    	char ch[11] = "133"; // 10 chiffres + zéro terminal	char ch2[11];
    	sprintf(ch2, "%010s", ch);
    	strncpy(ch, ch2,11);

  11. #10
    physiquantique

    Re : addition de nombres stocké sous forme de char

    Comme ceci , avec des pointeurs (que je ne maitrise absolument pas ... vu que y en avait pas en vb.net ) :

    Code:
    /* ADDITION NOMBRE ARBITRAIREMENT GRANDS */
    /* Un jour de pluie */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    char * zeros(char a[],int n);
    
    int main()
    {
      char a[] = "100000000000000000" ; /* Nombres pour tester*/
      char b[]="1" ;
      char * pointeura;
      char * pointeurb;
      int itemp =0;
      int retenue=0;
      int tempa,tempb,lena,lenb;
      lena =(int)strlen(a);        /*Longueurs des deux nombres*/
      lenb=(int)strlen(b);
      if (lena >lenb)    /*On égalise les longueurs (comme chez le coiffeur)*/
        {
          pointeurb=zeros(b,lena-lenb); 
          pointeura=a;
        }  
      else
        {
          pointeura =zeros(a,lenb-lena);
          pointeurb=b;
        }
      char result[strlen(pointeurb)+1];
      int j=0;
      for (j=0;j<strlen(pointeurb)+1;j++)
        {
          result[j]='0';
        } 
      int i=(int)strlen(pointeurb)-1; /* Initialisation de i*/
      printf("longueur : %d \n",i);
      while (i>=0)
        {
          tempa=pointeura[i]-'0';            /* On lit le ieme chiffre*/
          printf("lecutre a : %d\n",tempa);
          tempb=pointeurb[i]-'0';
          printf("lecutre  b: %d\n",tempb);
          itemp=tempa+tempb+retenue; /*chiffre de a + chiffre de b +retenue*/
          if (itemp>9)
    	{
    	  retenue=1;
    	  itemp=itemp-10;
    	  printf("chiffre[%d] %d \n",i+1,itemp);
    	  result[i+1]=itemp+'0';
    	}
          else
    	{
    	  retenue=0;
    	  result[i+1]=itemp+'0';
    	  printf("chiffre[%d] :  %d \n",i+1,itemp);   
    	}
    
          i=i-1;
        }
    
      /* Si la retenue n'est pas nulle après la boucle*/
      if (retenue!=0)
        {
          result[0]='1';
          printf("chiffre[0] = 1\n");
        }
      else
        {
          result[0]='0';
      }
    
      printf("%s \n",result);
    }
    
    /* fonction qui ajoute n zeros en début de nombre (le coiffeur)*/
    char * zeros(char nombre[],int n)
    {
      int i=0;
      int len=(int)strlen(nombre);
      char * c=malloc((strlen(nombre)+n)*sizeof(*c));
      char d[n];
      
      while (i<n)
        {
          d[i]='0';
          c[i]='0';
          i=i+1;
        }
      i=0;
      strcat(c,nombre);
      
      printf("zeros : arg :%s \n",c);
      return c;
    }
    vivons avec légerté

  12. #11
    physiquantique

    Re : addition de nombres stocké sous forme de char

    Ah bah c'est bon en modifiant : "char result[...]" en déclarant result comme un pointeur de taille appropriée.

    Le bon résultat à tous les coups , quelque soit la taille ... merci

    La seule chose que j'ai du mal à comprendre , c'est l'obligation d'utiliser des pointeurs : ca vient surement du fait que j'ai commencé par vb.net.
    Dernière modification par physiquantique ; 09/11/2014 à 10h45.
    vivons avec légerté

  13. #12
    Jack
    Modérateur

    Re : addition de nombres stocké sous forme de char

    Vu que tu ne travailles pas avec des tableaux de taille variable, je ne vois pas trop l'intérêt de passer par de l'allocation dynamique de mémoire (avec les pointeurs que ça implique).

    Il me semblait que ma façon de mettre des 0 en tête de la chaîne était "un peu" plus simple que la tienne.

  14. #13
    physiquantique

    Re : addition de nombres stocké sous forme de char

    Citation Envoyé par Jack Voir le message
    Vu que tu ne travailles pas avec des tableaux de taille variable, je ne vois pas trop l'intérêt de passer par de l'allocation dynamique de mémoire (avec les pointeurs que ça implique).

    Il me semblait que ma façon de mettre des 0 en tête de la chaîne était "un peu" plus simple que la tienne.
    Pardon , je n'avais pas compris votre réponse : je croyais qu'il fallait que je fasse des tableaux dynamiques. Je ne comprends pas bien ce que font sprintf et strncat ?

    dans la foulée , voilà la soustraction :

    Code:
    char * zeros(char nombre[],int n);
    int biggerthan(char nombre1[],char nombre2[]);
    
    int main(int argc,char* argv[])
    {
      char a[NMAX];
      char b[NMAX];
      
      printf("a=?\n");
      scanf("%s",a);
      printf("b=?\n");
      scanf("%s",b);
      char * pointeura;
      char * pointeurb;
      char *p1;
      char *p2;
      int i;
      char signe;
      if (strlen(a)>strlen(b))
        {
          p1=a;
          p2=zeros(b,strlen(a)-strlen(b));
          i=strlen(a)-1;
        }
      else
        {
          p1=zeros(a,strlen(b)-strlen(a));
          p2=b;
          i=strlen(b)-1;
        }
      if(biggerthan(p1,p2)==0)
        {
          pointeura=p2;
          pointeurb=p1;
          signe='-';
          printf("plus petit --> -(b-a)\n");
        }
      else
        {
          pointeura=p1;
          pointeurb=p2;
          signe='+';
          printf("ok a-b\n");
        }
      char * resultat = malloc((i+3)*sizeof(*a));
      int tempa,tempb,itemp;
      int retenue=0;
      while (i>=0)
        {
          tempa=pointeura[i]-'0';
          tempb=pointeurb[i]-'0';
          itemp=tempa-tempb-retenue;
          if (itemp<0)
    	{
    	  retenue=1;
    	  itemp=itemp+10;
    	  printf("chiffre[%d]=%d \n",i+1,itemp);
    	}
          else
    	{
    	  retenue=0;
    	  printf("chiffre[%d]=%d \n",i+1,itemp);
    	}
          resultat[i+1]=itemp+'0';
          i=i-1;
        }
      if (signe=='-')
        {
         
          resultat[0]='-';
        }
      else
        {
         
          resultat[0]='+';
        }
      printf("resultat: %s\n",resultat);
      return 0;
    }
    utilisant la fonction "biggerthan(a,b)" renvoyant 1 si a>=b et 0 sinon :

    Code:
    int biggerthan(char nombre1[],char nombre2[])
    {
      int resultat=0;
      char * p1 = NULL;
      char * p2 = NULL;
      int i=0;
      int n;
      if (strlen(nombre1)>strlen(nombre2)) /* tous le monde chez le coiffeur*/
        {
          p1=nombre1;
          p2=zeros(nombre2,strlen(nombre1)-strlen(nombre2));
          n=strlen(nombre1)-1;
    	       }
          else
    	{
    	  p1=zeros(nombre1,strlen(nombre2)-strlen(nombre1));
    	  p2=nombre2;
    	  n=strlen(nombre2)-1;
    	}    
      while(i<=n)
        {
          if (p1[i]==p2[i])
    	{
    	  resultat=1;
    	  printf("%c = %c",p1[i],p2[i]);
    	}
          if(p1[i]<p2[i])
    	{
    	  resultat=0;
    	  printf("%c < %c",p1[i],p2[i]);
    	  break;
    	}
          if(p2[i]<p1[i])
    	{
    	  resultat=1;
    	  printf("%c < %c",p2[i],p1[i]);
    	  break;
    	}
          i=i+1;
        }
      return resultat;
    
    }
    Dernière modification par physiquantique ; 09/11/2014 à 15h05.
    vivons avec légerté

  15. #14
    Jack
    Modérateur

    Re : addition de nombres stocké sous forme de char

    Pardon , je n'avais pas compris votre réponse : je croyais qu'il fallait que je fasse des tableaux dynamiques.
    J'ai écrit ceci dans un précédent message:
    Il faudra donc définir une taille de tableau correspondant au nombre maxi de chiffre des nombre que tu veux additionner. Si le nombre de caractères ne doit pas être limité, il faudra créer des tableaux dynamiques.
    J'émettais 2 hypothèses: les chaines avaient une longueur limitée ou non. Je ne sais toujours pas laquelle tu désires utiliser.
    Je répète donc que si les nombres possèdent un nombre de chiffres maxi défini au lancement du programme, pas besoin de tableau dynamique.
    Je ne comprends pas bien ce que font sprintf et strncat
    RTFM! tape "man sprintf" ou "man strncpy" dans ton navigateur préféré.
    utilisant la fonction "biggerthan(a,b)" renvoyant 1 si a>=b et 0 sinon :
    Si les deux chaines sont de même taille, comblées par des 0 à gauche, un simple appel à la fonction strncmp (man strncmp) devrait te permettre de savoir quel nombre est le plus grand.

    En fait, tu est en train de réinventer la roue, la plupart des fonctions de traitement des chaines existant déjà dans les librairies standard du C.
    Dernière modification par Jack ; 09/11/2014 à 15h20.

  16. #15
    physiquantique

    Re : addition de nombres stocké sous forme de char

    L'idéal pour*moi serait de ne pas avoir à limiter la taille des chaines pour pouvoir manipuler des nombres aussi grands qu'on veut .
    Et de reprogrammer les fonctions quand elles font des trucs compliqués .

    Mais je sais pas comment récupérer avec du scanf une chaine de taille non définie .
    vivons avec légerté

  17. #16
    WizardOfLinn

    Re : addition de nombres stocké sous forme de char

    Tu te complique la vie à travailler directement avec des chaines de caractères plutôt d'avec des tableaux d'entier.
    Et commence par définir une structure représentant un nombre de longueur arbitraire, avec ses fonctions élémentaires d'allocation/libération de la mémoire.

    Quelques chose comme :

    typedef struct {
    int *chiffres;
    int n;
    } NOMBRE;


    Ensuite :

    NOMBRE* Alloc(int n)
    {
    // Alloue un nombre de n chiffres et initialise à 0
    }

    void Free(NOMBRE *)
    {
    // Libération de la mémoire
    }

    Et la taille maximale du résultat d'une opération est connue avant l'exécution des opérations arithmétiques élémentaires , donc on connait la taille des tableaux à allouer avant d'exécuter une opération.

    Plus qu'à définir les fonctions :
    NOMBRE* Addition(const NOMBRE* c1, const NOMBRE* c2)
    NOMBRE* Soustraction(const NOMBRE* c1, const NOMBRE* c2)
    NOMBRE* Multiplication(const NOMBRE* c1, const NOMBRE* c2)
    void Division(const NOMBRE* c1, const NOMBRE* c2, NOMBRE** quotient, NOMBRE** reste)

    Et prévoir à la fin une fonction pour repasser en chaine de caractères pour afficher les résultats.
    Avec ça, à toi les millions de décimales de PI

  18. #17
    physiquantique

    Re : addition de nombres stocké sous forme de char

    pourquoi forcément pi ?

    Et en utilisant cette structure , je peux adapter directement ce que j'ai fait pour les chaines de caractères ?

    (j'ai la flemme de recommencer ^^).
    Dernière modification par physiquantique ; 13/11/2014 à 11h54.
    vivons avec légerté

  19. #18
    Jack
    Modérateur

    Re : addition de nombres stocké sous forme de char

    Citation Envoyé par physiquantique Voir le message
    L'idéal pour*moi serait de ne pas avoir à limiter la taille des chaines pour pouvoir manipuler des nombres aussi grands qu'on veut .
    Et de reprogrammer les fonctions quand elles font des trucs compliqués .

    Mais je sais pas comment récupérer avec du scanf une chaine de taille non définie .
    Une boucle avec getchar ????

  20. #19
    whoami

    Re : addition de nombres stocké sous forme de char

    Bonjour,

    Si ton problème est de faire des calculs multi-précision (ça s'appelle comme ça ), le mieux est sans le moindre doute d'utiliser une bibliothèques existant.

    Il y a la plus connue GMP, qui est gratuite et très performante.

    Si c'est à titre d'exercice pour apprendre, alors continue, même avec des données de type char, les algorithmes de calcul ne changeant pas, mais ne t'attends pas à des performances fabuleuses.

    Mais je vois que tu parles de "trucs compliqués", et là, il te faudra passer le tout dans des types adaptés à ton processeur, et programmer les fonctions basiques (+, -, *, /) en assembleur, car pour être performant, il te faudra utiliser des possibilités que les langages de haut niveau ne savent pas exploiter.

    Pour info, j'ai développé une telle bibliothèque : première version en 1986, et depuis je maintiens des versions optimisées pour les nouveaux processeurs. Ça ne se fait pas tout seul, un gros boulot, même pour une version relativement basique mais optimisée.

    Petite précision : il est inutile de me demander une version de ma bibliothèque, c'est mon employeur qui en est propriétaire.

    À mon avis, la meilleure solution est donc de faire quelques bricoles comme tu as commencé, histoire de comprendre les algorithmes, puis, pour l'utilisation réelle, récupérer GMP, et en route pour les applications efficaces.

    Dans tous les cas, bon courage pour la suite.

  21. #20
    physiquantique

    Re : addition de nombres stocké sous forme de char

    Bonjour :

    à whoami : Merci . Effectivement , mon but est simplement d'essayer d'écrire mes propres programmes aussi simples et peu performants soient ils . J'avais commencé en vb.net avec la programmation d'un "crypteur rsa" en commencant par des petites clés puisque j'utilisais le type integer . Pourtant il existait bel et bien des fonctionnalités de cryptage , mais j'avais envie d'écrire mon propre crypteur . Puis j'ai voulu pouvoir utiliser des clés aussi grande que voulu , en laissant de coté la performance pour un moment . C'est là que j'ai commencé à créer des fonctions d'opérations sur les entiers stockésdans des tableaux de caractères . Bref , j'admire beaucoup ceux qui ont réussis à programmer une telle bibliothèque , et je ne compte pas écrire des codes aussi compliqués , juste des codes qui marchent , même s'ils ne sont pas performant (j'essaierai par la suite de les optimiser , mais je ne suis pas sur que j'en connaisse assez sur la programmation et l'informatique en général) .


    Merci en tout cas de votre soutient .

    Bonne journée (en ce moment elles sont propices à la programmation vue la pluie qui dégringole dehors).
    vivons avec légerté

  22. #21
    physiquantique

    Re : addition de nombres stocké sous forme de char

    à WizardofLynn : je crois que je n'ai pas compris ce que réprésente *chiffres , ni comment l'utiliser .
    vivons avec légerté

  23. #22
    physiquantique

    Re : addition de nombres stocké sous forme de char

    Comment je pourrais faire pour que , dans une boucle , j'incrémente une variable (ou quelquechose) de la façon suivante (sachant que quelquechose va forcément avoir une taille variable , j'imagine donc qu'il faut faire de l'allocation dynamique , mais je suis pas encore très à l'aise avec tout ça ).
    Code:
    while(...)
    {
    quelquechose = addition(quelquechose,b);
    }
    où addition est de la forme suivante :

    Code:
    char * addition(char nombre1[],char nombre2[])
    {
    char * c;
    ... /* écrit le résultat de l'addition dans c*/
    return c ; 
    }
    C'est pour la fonction multiplication ("quelquechose" c'est pour le résultat final, et b ca contient le résultat de multichiffre(nombre1,chiffre[i] du nombre2) )
    vivons avec légerté

  24. #23
    WizardOfLinn

    Re : addition de nombres stocké sous forme de char

    Citation Envoyé par physiquantique Voir le message
    à WizardofLynn : je crois que je n'ai pas compris ce que réprésente *chiffres , ni comment l'utiliser .
    C'est l'équivalent de ta chaine de caractères. Et j'aurais aussi bien pu mettre un tableau char*, j'avais mis int* pour éviter la confusion avec une chaine.
    Par contre, on stocke des char entre 0 et 9, plutôt qu'entre '0' et '9', pour éviter de passer son temps à ajouter et soustraire des '0', ça allège le coeur des boucles de calcul.
    Voir ci-dessous un exemple de solution. Ce n'est certainement pas optimal ni comparable à une vraie librairie comme GMP, mais la fonction d'addition est déjà plus simple : une fois passé quelques allocations mémoire, la boucle de calcul tient en quelques lignes.
    Petit programme écrit en 1/2h, j'ai vérifié que ça compile et donne les bons résultats.
    Pour traiter les nombres négatifs, tu peux ajouter un champ 'signe' à la structure NOMBRE, et adapter en conséquence la fonction d'addition.
    Après, il te reste à traiter soustraction, multiplication, division...
    Un programme plus solide vérifierait aussi que les chaines de caractères d'entrée sont valides, et éventuellement les allocations mémoires si tu commences à manipuler des nombres avec des millions de chiffres.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct {
    	char* chiffres; 
    	int n;  /* nombre de chiffres */
    } NOMBRE;
    
    /*	Allocation d'un nombre de n chiffres */
    NOMBRE* Alloc(int n)
    {	int i;
    	NOMBRE* N = (NOMBRE*)malloc(sizeof(NOMBRE));
    	N->chiffres = (char*)malloc(n*sizeof(char));
    	N->n = n;
    	for (i = 0; i < n; i++)
    		N->chiffres[i] = 0;
    	return N;
    }
    
    /*	Libération mémoire */
    void Free(NOMBRE* N)
    {	free(N->chiffres);
    	free(N);
    }
    
    /*	Addition */
    NOMBRE* Addition(const NOMBRE* N1, const NOMBRE* N2)
    {	int i, ns;
    	char r, a;
    	NOMBRE* S;
    
    	/*	Evaluation de la taille du résultat */
    	if (N1->n > N2->n) ns = N1->n + 1;
    	else ns = N2->n + 1;
    
    	/*	Initialisation du résultat et copie de N1 dans le résultat */
    	S = Alloc(ns);
    	for (i = 0; i < N1->n; i++)
    		S->chiffres[i] = N1->chiffres[i];
    
    	/*	Addition */
    	for (i = 0, r = 0; i < N2->n; i++)
    	{	a = S->chiffres[i] + N2->chiffres[i] + r;
    		S->chiffres[i] = a%10;
    		r = a/10;
    	}
    	/*   Propagation de la retenue */
    	while (r != 0)
    	{	a = S->chiffres[i] + r;
    		S->chiffres[i] = a%10;
    		r = a/10;
    		i++;
    	}
    
    	return S;
    }
    
    /*	Affichage d'un nombre */
    void Afficher(const NOMBRE* N)
    {	int i, n;
    
    	n = N->n-1;
    	while ((N->chiffres[n] == 0) && (n > 1))	//	Elimination des '0' non significatifs
    		n--;
    	for (i = n; i >= 0; i--)
    		printf("%c", N->chiffres[i]+'0');
    	printf("\n");
    }
    
    /*	Initialisation à partir d'une chaine de caractères */
    NOMBRE* InitNombre(const char* chaine)
    {	int i, n = strlen(chaine);
    	NOMBRE* N = Alloc(n);
    
    	for (i = 0; i < n; i++)
    		N->chiffres[i] = chaine[n-i-1] - '0';
    
    	return N;
    }
    
    #define MAXSTR 10000
    
    /* Programme de test */
    void main(void)
    {	NOMBRE *N1, *N2, *S;
    	char nbr1[MAXSTR], nbr2[MAXSTR];
    	int c;
    
    	do
    	{	/* Initialisation nombre 1 */
    		printf("Nombre 1 : ");
    		scanf("%s", nbr1);
    		N1 = InitNombre(nbr1);
    
    		/*	Initialisation nombre */
    		printf("Nombre 2 : ");
    		scanf("%s", nbr2);
    		N2 = InitNombre(nbr2);
    
    		/*	Somme */
    		S = Addition(N1, N2);
    
    		/*	Affichage */
    		printf("Somme = ");
    		Afficher(S);
    
    		/*	Nettoyage mémoire */
    		Free(N1);
    		Free(N2);
    		Free(S);
    
    		/*   Suite ? */
    		printf("Continuer (1=oui) ? ");
    		scanf("%d", &c);
    
    	} while (c == 1);
    }

  25. #24
    physiquantique

    Re : addition de nombres stocké sous forme de char

    Bonjour ,

    wouaw ! ça fait tout de suite pro ! .

    Par contre , je comprends pas bien la "propagation de la retenue" . Pourquoi faut il faire une boucle à part pour la traiter ?


    Merci .
    vivons avec légerté

  26. #25
    physiquantique

    Re : addition de nombres stocké sous forme de char

    petit programme écrit en 1/2 h
    Attention : 1/2h dans l'horloge d'un pro , ça fait un an dans l'horloge d'une bleusaille (pu*** il me fait déconner la tête le film "Interstellar") .
    vivons avec légerté

  27. #26
    WizardOfLinn

    Re : addition de nombres stocké sous forme de char

    Citation Envoyé par physiquantique Voir le message
    Bonjour ,
    wouaw ! ça fait tout de suite pro ! .
    Par contre , je comprends pas bien la "propagation de la retenue" . Pourquoi faut il faire une boucle à part pour la traiter ?
    Merci .
    On pourrait en effet tout mettre dans la même boucle, mais dans ce cas, il faut normaliser la longueur des opérandes, ce qui fait des opérations supplémentaires, ou faire des tests pour vérifier qu'on ne déborde pas du tableau de N2. Pas forcément plus économique.
    Examine l'exécution pour le cas N1=9999 et N2=1.
    La boucle principale est exécutée une fois, car N2 ne compte qu'un chiffre.
    Par contre, la retenue doit être encore propagée sur les 3 chiffres suivants du résultat.
    On pourrait normaliser N2 à 0001 et écrire une boucle unique.

    A+

  28. #27
    physiquantique

    Re : addition de nombres stocké sous forme de char

    Bonjour ,

    je me suis remis aujourdhui sur cette histoire .

    J'ai un peu avancé : j'ai réussi à programmer la multiplication nombre-chiffre puis nombre-nombre plutôt convenablement . A part quelques problèmes (dans l'ordre croissant : du moins embetant au plus embetant) :

    1. Je n'ai pas encore programmer une fonction pour enlever les zeros de début de nombres .(ca ne saurait tarder).

    2. Pour la multiplication , tout se passe bien si je multiplie le plus grand nombre toujours à gauche , mais dans le cas contraire , si le nombre est vraiment grand , le résultat est faux .

    3. En chemin , j'essaye de programmer le modulo , qui s'execute bien pour les petits nombres , mais pour les grands nombres , j'obtient rapidement une erreur :

    Code:
     modulo.out: malloc.c:2372: sysmalloc:
     Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) 
    || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1))
     & ~((2 *(sizeof(size_t))) - 1)))
     && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed.
    Abandon (core dumped)
    Je pense bien sur que ca ne sert à rien de construire par dessus multiplication qui n'est pas encore bien aboutit , et que cette erreur provient des erreurs précedentes ... Mais je ne comprends pas ce qu'elle dit .

    Merci d'avance .
    Bonne journée.
    vivons avec légerté

  29. #28
    physiquantique

    Re : addition de nombres stocké sous forme de char

    En fait , ma mutliplication produit des résultats bizzarres aussi :

    Code:
     char *multiplication(char a[],char b[])
    {
      nombre liste[strlen(b)];
      int i=strlen(b)-1;
      while(i>=0)
        {
          liste[i].chiffres=multichiffre(a,b[i]-'0',(int)strlen(b)-i-1); /* liste des multchiffre*/
          printf("+ %s\n",liste[i].chiffres);
          i=i-1;
        }
      i=1;
      while(i<=strlen(b)-1) /* somme des liste[i]*/
        {
          liste[i].chiffres=addition(liste[i].chiffres,liste[i-1].chiffres);
          i=i+1;
        }
      /*suppression des zeros en début*/
      zerosdebut(&liste[strlen(b)-1].chiffres);
      return liste[strlen(b)-1].chiffres;
    }
    char *multichiffre(char a[],int b,int n)
    {
      char *resultat  = malloc((strlen(a)+n+1)*sizeof(*resultat));
      int retenue=0;
      int chiffre=0;
      char z[]="";
     
      int i=strlen(a)-1;
      while (i>=0)
        {
          chiffre=(a[i]-'0')*b+retenue;
          if (chiffre>9)
    	{
    	  retenue=(chiffre-chiffre%10)/10;
    
    	  chiffre=chiffre%10;
    
    	}
          else
    	{
    	  retenue=0;
    	}
    	  
    	  resultat[i+1]=chiffre+'0';
    	
    	  i=i-1;
        }
          resultat[0]=retenue+'0';
          int j=0;
          for (j=strlen(a)+1;j<(strlen(a)+n+1);j++)
    	{
    	  resultat[j]='0';
    	}
         
          return resultat;
    }
    Pour les petits nombres (moins d'une quinzaine de chiffres) , ca marche bien , mais au dessus , ca me donne un résultat "presque bon" , dans le sens où les derniers caractères de sont pas bons . Lorsque je rajoute des printf pour voir la multiplication détaillée , ca me donne ca :

    Code:
    EXEMPLE D'AFFICHAGE pour 10000000000000000000000000000 * 1000000000000000000000000000000000000
    
    CHAQUE LIGNE CORRESPOND A LA MULTIPLICATION i-eme CHIFFRE avec NOMBRE 
    
    + 000000000000000000000000000000
    + 000000000000000000000000000000000000000
    (etc...)
     0000000000000000000000000000000000000000� : LIGNE BIZZARRE
    + 00000000000000000000000000000000000000000
    (etc...)
    + 0000000000000000000000000000000000000000000000000000000
    + 00000000000000000000000000000000000000000000000000000000�	 : LIGNE BIZZARRE
    + 000000000000000000000000000000000000000000000000000000000
    (etc...)
    + 010000000000000000000000000000000000000000000000000000000000000000
    
    
    résultat : 1000000000000000000000000000000000000000000000000000000000000000902a�
    Dernière modification par physiquantique ; 30/11/2014 à 13h54.
    vivons avec légerté

  30. #29
    Chanur

    Post Re : addition de nombres stocké sous forme de char

    Citation Envoyé par physiquantique Voir le message
    Code:
     modulo.out: malloc.c:2372: sysmalloc:
     Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) 
    || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1))
     & ~((2 *(sizeof(size_t))) - 1)))
     && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed.
    Abandon (core dumped)
    Je pense bien sur que ca ne sert à rien de construire par dessus multiplication qui n'est pas encore bien aboutit , et que cette erreur provient des erreurs précedentes ... Mais je ne comprends pas ce qu'elle dit .
    Elle dit que la mémoire est corrompue.
    Les causes les plus fréquentes sont un dépassement dans l'écriture d'une zone allouée dynamiquement ou le fait de libérer de la mémoire non allouée (par exemple en lançant deux fois free() ).
    Elle dit aussi que l'image du process a été écrite dans un fichier core, qui permet d'aller voir où en était le programme au moment du plantage (ligne de code, pile d'appel des fonctions, valeur des variables ...)
    gdb sait lire le fichier core. Il faut compiler avec l'option -g pour avoir des infos lisibles.

    Citation Envoyé par physiquantique Voir le message
    En fait , ma mutliplication produit des résultats bizzarres aussi :

    Code:
     0000000000000000000000000000000000000000� : LIGNE BIZZARRE
    Typiquement une chaîne de chaîne de caractères qui ne se termine pas par un caractère nul.
    D'ailleurs tu ne mets PAS de caractère nul à la fin de ton résultat ...
    Ce qui se conçoit bien s'énonce clairement ; et les mots pour le dire arrivent aisément.

  31. #30
    physiquantique

    Re : addition de nombres stocké sous forme de char

    Bonjour ,
    je viens de rajouter des caractères null à la fin des résultats (dans addition et multichiffre) , et toujours le même résultat . Un exemple : multiplication de 11*222222222222.

    Code:
    + 022
    + 0220
    + 02200
    + 022000
    + 0220000
    + 02200000
    + 022000000
    + 0220000000
    + 02200000000
    + 022000000000
    + 0220000000000
    + 02200000000000
    resultat: 244444444442010
    j'ai donc l'impression que c'est quand je fait :
    Code:
    while(i<=strlen(b)-1) /* somme des liste[i]*/
        {
          liste[i].chiffres=addition(liste[i].chiffres,liste[i-1].chiffres);
          i=i+1;
        }
    qu'il ya un poblème (liste est un tableau de nombres , à longueur_de_b - élements , chaque élement contenant le résultat de multichiffre(a,b[i]) ) .

    Ai-je le droit de faire cela ?

    Merci d'avance .
    Bonne journére .
    vivons avec légerté

Page 1 sur 2 1 DernièreDernière

Discussions similaires

  1. Programme addition de nombres (débutant)
    Par marcantoine75 dans le forum Électronique
    Réponses: 2
    Dernier message: 01/04/2012, 22h23
  2. Tout petit insecte en forme de char d'assaut
    Par zyket dans le forum Identification des espèces animales ou végétales
    Réponses: 2
    Dernier message: 20/07/2011, 16h45
  3. Déterminer la forme algébrique d'un nombre complexe écrit sous forme trigonométrique
    Par invite8412c11b dans le forum Mathématiques du collège et du lycée
    Réponses: 6
    Dernier message: 13/01/2009, 21h53
  4. Factorisation d un nombre premier sous la forme P=(x-1)(y-1) (x,y deux nombres premiers)
    Par invite37f01ff2 dans le forum Mathématiques du supérieur
    Réponses: 6
    Dernier message: 10/12/2008, 11h57
  5. [C]-Conversion Int -> Char, Float -> Char, ...
    Par jorg1n dans le forum Électronique
    Réponses: 2
    Dernier message: 25/06/2008, 11h05