IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Opération nombres infinis


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2014
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Octobre 2014
    Messages : 22
    Par défaut Opération nombres infinis
    Bonsoir,
    Je suis étudiant en informatique et en ce moment nous apprenons le C. Nous sommes sur un projet ce nommant la "bistromathique" pour les adeptes.
    Le but de ce projet c'est de crée une calculatrice gérant des nombres infinies ( jusqu'a la mémoire on va dire...).

    Donc nous faisons étape par étape et pour le moment je suis sur : gérer les additions à l'infini.
    Je précise avant toute chose que cette partie la devait déjà être rendu donc en aucun cas j'utilise cette discussion pour avoir une bonne note mais plutôt pour pouvoir savoir et ensuite avancer.

    J'ai compris qu'il faut fonctionner comme étant petit, calculer caractère par caractère puis gérer une retenue. Cependant voila, le nombre que j'affiche à la fin ne m'affiche pas le 1 ! Je m'explique par exemple :

    107 + 5 = 102 alors que ca devrait etre 112
    53 + 28 = 71 au lieu de 81

    (il additionne pas le caractère d'avant) sachant que je sais que dans une addition, la retenue ne pas pas dépasser 1..!

    Voila en esperant trouver quelqu'un qui puisse m'eclairer ! (le soucis est probablement dans addition_2 dans le 2 ou 3 eme if, mais après 100000 tentatives, je ne COMPREND pas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
     
    #include <stdlib.h>
    #include "my.h"
     
    int     check_error(char *str1, char *str2)
    {
      int   i;
     
      i = 0;
      if (str1[0] == '-' || str1[0] == '+')
        i = 1;
      while (str1[i] != '\0')
        {
          if (my_isnum(str1[i]) == 1)
            i = i + 1;
          else
            return (1);
        }
      i = 0;
      if (str2[0] == '-' || str2[0] == '+')
        i = 1;
      while (str2[i] != '\0')
        {
          if (my_isnum(str2[i]) == 1)
            i = i + 1;
          else
            return (1);
        }
      return (0);
    }
     
    int     addition_2(int a, int b, char *result, char *str2, char *str1, int ret)
    {
      ret = 0;
      result = malloc(a + 1);
      if (result == NULL)
        return (1);
      result[a] = '\0';
     
      while (a != 0)
        {
          if (b <= 0)
            str2[b - 1] = '0';
          if (result[a - 1] = ((str2[b - 1] + str1[a - 1]) - 48 <= '9'))
            {
              result[a - 1] = (str2[b - 1] + str1[a - 1] - 48);
            }
          else
            {
              result[a - 1] = ((str2[b - 1] + str1[a - 1] - 48) - 10);
            }
          a = a - 1;
          b = b - 1;
        }
       my_putstr(result);
      my_putchar('\n');
      return (0);
    }
    int     addition(char *str1, char *str2)
    {
      int   a;
      int   b;
      int   ret;
      char  *str_tp1;
      char  *str_tp2;
      char  *result;
     
      a = my_strlen(str1);
      b = my_strlen(str2);
      if (b > a)
        {
          my_swap(&a, &b);
          str_tp1 = malloc(a * sizeof(char) + 1);
          if (str_tp1 == NULL)
            return (1);
          str_tp2 = malloc(b * sizeof(char) + 1);
          if (str_tp2 == NULL)
            return (1);
          str_tp1 = str1;
          str_tp2 = str2;
          str1 = str_tp2;
          str2 = str_tp1;
        }
      addition_2(a, b, result, str2, str1, ret);
    }
     
    int     main(int argc, char **argv)
    {
      if (argc != 3)
        {
          write(2, "Bad enter, retry\n", 24);
          return (0);
        }
      if (check_error(argv[1], argv[2]) == 1)
        return (0);
      addition(argv[1], argv[2]);
      return (0);
    }

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 832
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Tu as parfaitement saisi le principe: pour travailler sur des nombres virtuellement infinis, tu dois les traiter comme au primaire: chiffre par chiffre avec la retenue. Maintenant il y a beaucoup de maladresses dans ton code, il est bien trop lourd ce qui ne facilite pas la recherche de bugs.
    Tout d'abord ta fonction de vérification: pourquoi avoir dupliqué le code de vérif ? Pourquoi ne pas faire une fonction de vérification dédiée à vérfiier un nombre quelconque et l'appeler ensuite pour tous les nombres que tu dois vérifier ???

    Autre chose: ta fonction my_isnum semble retourner 1 quand le caractère est un nombre correct et 0 quand il ne l'est pas... mais ta fonction check_error c'est l'inverse: elle renvoie 0 quand ton nombre est un nombre correct et 1 quand il ne l'est pas. C'est déroutant. Essaye de prendre une seule logique et de t'y tenir. Et au lieu d'avoir une fonction "check_error," tu la replaces par une autre "is_correct". Et au lieu de renvoyer 0/1, tu renvoies 0/élément reçu

    Exemple possible
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    char *is_correct (char *nbr)
    {
        char *pt=nbr;
        if (*pt == '+' || *pt == '-') pt++;
        do {
            if (my_isnum(*pt) == 0) return NULL;
        } while (*pt++);
        return nbr;
    }

    Renvoyer 1 au lieu de nbr ne changerait rien (tout nombre différent de 0 est "vrai") mais généralement les programmeurs de C n'aiment pas les choses nouvellement inutiles (or "1" est nouveau et n'apporte pas plus de renseignement que nbr lui-même)

    Ensuite la fonction addition_2. Pourquoi diable reçoit-t-elle des éléments qu'elle pourrait elle-même calculer ? Le "a" et le "b", ce sont bien les longueurs des chaines non ? A ce propos, tu devrais aussi mettre des noms plus parlants à tes paramètres. Donc ces longueurs, ta fonction n'est-elle donc pas capable de les trouver ? Et c'est quoi ce paramètre "ret" qui arrive sans valeur connue et qui est immédiatement mis à 0 ?? Est-ce que tu sais réellement en fait à quoi sert un paramètre de fonction ???
    Donc dans cette fonction (dont le malloc initial ne sera jamais libéré), dis-moi où est-ce que tu gères la retenue ? A quel moment ecris-tu un truc du type "si le résultat est supérieur à 9 j'enlève 10 et je mets 1 de coté pour le rang suivant" ???

    Accessoirement c'est quand-même dommage ces 3 lignes presque identiques où l'opération est quand-même toujours faite au-moins 2 fois alors que finalement, le calcul étant déjà fait (et aurait même pu être mémorisé s'il avait été bien écrit), ne reste plus qu'à vérifier avec '9' pour éventuellement enlever 10 !!!
    A propos du calcul justement, je ne sais pas si t'as appris les priorités des opérateurs mais si tu dois comparer une opération avec affectation intégrée, alors tu dois entourer l'affectation de l'opération de parenthèses parce que écrire if (var=operation <= '9') va commencer par faire operation <= '9' pour mettre le résultat dans "var". Dans la même lignée, les parenthèses autour de str2[b - 1] + str1[a - 1] sont totalement inutiles vu que l'addition est associative (donc (a+b)-c est égal à a+b-c). Tu as le droit de ne pas connaitre les priorités des opérateurs vu que tu débutes en C mais tu n'as pas le droit de ne pas connaitre les propriétés de l'addition vu qu'elles sont enseignées au primaire.

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    if ((result[a - 1] = str2[b - 1] + str1[a - 1] - '0') > '9')
    {
        // Le résultat dépasse 10
        result[a - 1]-=10;
     
        // Et je gère la retenue !!!
        ...
    }
    // Sinon ici je ne fais rien vu que result[a - 1] a déjà le bon résultat !!!

    Autres détails: je ne comprends pas trop la partie du code où tu testes si b (une longueur) est inférieure à 0...

    Donc voilà. Réfléchis à ce que tu fais quand tu le fais et tu comprendras plus facilement...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Membre averti
    Homme Profil pro
    Lycéen
    Inscrit en
    Octobre 2014
    Messages
    22
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 29
    Localisation : France, Aisne (Picardie)

    Informations professionnelles :
    Activité : Lycéen

    Informations forums :
    Inscription : Octobre 2014
    Messages : 22
    Par défaut
    Bonjour,
    Merci de votre réponse, vous m'avez beaucoup aidé ! Mon maintenant mon programme semble fonctionner, il checke même les erreurs et gère la retenue ! (je n'ai pas encore optimisé tout le programme comme vous m'avez dit de le faire par exemple pour la fonction qui prenait en compte a et b oui c'est bel et bien la longueur des chaînes mais vous me dîtes que addition2 peut le faire, mais dans ma fonction addition, j'en ai besoin pour swap pour savoir quelle est la plus grande chaîne ! )

    Cependant il me reste encore un léger souci… Je m'explique :
    Quand je fais 107 + 5, par exemple, il n'y a aucun souci : il gère la retenue et me renvoie maintenant 112.
    Mais quand ma chaîne doit contenir une retenue sur le dernier chiffre, celui-là ne l'affiche pas !
    Par exemple : 500 + 500 il va m'afficher : 000 et non 1000

    J'ai créé une condition (juste au dessus des printf j'ai essayé de déboguer) pour tenter de retourner le 1. Bien évidemment, on me demande de retourner et non d'afficher donc écrire : my_putchar('1') ne marche pas !...
    Cependant le positionnement est bon puisque lorsque je teste, il me place bien le 1 où il faut. J'ai essayé plusieurs calculs à la position a = 0 mais je ne sais pas trop au final ce que je veux calculer pour afficher mon 1 ( si ce n'est que 5 + 5 = 10 pour 500 + 500)
    Je me demandais aussi si cela n'était pas un souci de malloc donc j'ai alloué un espace en plus ( ligne 40 ) mais sans résultat.
    Avez-vous une piste ? Merci encore de vos conseils. Dès que mon programme sera full fonctionnel, j'essayerai de gérer l'addition avec les - ! et ensuite j'essaierai de créer la fonction is_correct

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    #include <stdio.h>
    #include <stdlib.h>
    #include "my.h"
     
    int     check_error(char *str1, char *str2)
    {
      int   i;
     
      i = 0;
      while (str1[i] != '\0')
        {
          if (my_isnum(str1[i]) == 0)
            return (1);
          else
            i = i + 1;
        }
      i = 0;
      while (str2[i] != '\0')
        {
          if (my_isnum(str2[i]) == 0)
            return (1);
          else
            i = i + 1;
        }
      return (0);
    }
     
    int     addition_2(int a, int b, char *result, char *str2, char *str1)
    {
      result = malloc(a + 2);
      if (result == NULL)
        return (1);
      result[a] = '\0';
     
      while (a != 0)
        {
          if (b <= 0)
            str2[b - 1] = '0';
          if (result[a - 1] = str2[b - 1] + str1[a - 1] - '0' > '9')
            {
              printf("a = "); // mes printf sont la pour m'aider a visualiser                                                                                                                     
              printf("%d ", a);
              printf("b = ");
              printf("%d ", b);
              printf("str1 = ");
              printf("%s ", str1);
              printf("str2 = ");
              printf("%s ", str2);
     
              if (a == 1 && b == 1) // ici j'ai essayer d'afficher le 1 sans trop de succès.                                                                                                      
                {
                  result[a - 1] = str2[b - 1] + str1[a - 1];
                }
              result[a - 1] = (str2[b - 1] + str1[a - 1] - '0' - 10);
              str1[a - 2] = str1[a - 2] + 1;
            }
          else
            result[a - 1] = str2[b - 1] + str1[a - 1] - 48;
          a = a - 1;
          b = b - 1;
        }
      my_putstr(result);
      my_putchar('\n');
      free(result);
      return (0);
    }
     
    int     addition(char *str1, char *str2)
    {
      int   a;
      int   b;
      char  *str_tp1;
      char  *str_tp2;
      char  *result;
     
      a = my_strlen(str1);
      b = my_strlen(str2);
      if (b > a)
        {
          my_swap(&a, &b);
          str_tp1 = malloc(a * sizeof(char) + 1);
          if (str_tp1 == NULL)
            return (1);
          str_tp2 = malloc(b * sizeof(char) + 1);
          if (str_tp2 == NULL)
            return (1);
          str_tp1 = str1;
          str_tp2 = str2;
          str1 = str_tp2;
          str2 = str_tp1;
        }
      addition_2(a, b, result, str2, str1);
    }
     
    int     main(int argc, char **argv)
    {
      if (argc != 3)
        {
          write(2, "Bad enter, retry\n", 24);a
          return (0);
       }
      if (check_error(argv[1], argv[2]) == 1)
        {
          write(2, "Bad enter, only numbers retry\n", 32);
          return (0);
        }
      addition(argv[1], argv[2]);
      return (0);
    }

  4. #4
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2012
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2012
    Messages : 63
    Par défaut
    Salut,

    Je sais que le projet et fini mais tu a un souci de norme, addition_2(int a, int b, char *result, char *str2, char *str1) je conte 5 param moi ... tu doit en avoir 4 max relis la norme.

    Cdt,

    Takago.

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 832
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par takago Voir le message
    Je sais que le projet est fini mais tu as un souci de norme, addition_2(int a, int b, char *result, char *str2, char *str1) je compte 5 param moi ... tu dois en avoir 4 max relis la norme.
    Mouais, bonjour à toi aussi.
    Et en fait, 3 suffisent: addition_2(char *result, char *str2, char *str1) - a et b seront calculés par la fonction à partir de str1 et str2...

    Citation Envoyé par takago Voir le message
    Cdt,
    C'est vrai que d'écrire "cordialement" c'est super long et ça use prématurément les caractères "aeilmnor" de ton clavier...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Membre actif
    Homme Profil pro
    Étudiant
    Inscrit en
    Septembre 2012
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2012
    Messages : 63
    Par défaut
    Désole pour le Cdt c'est une habitude, pour le nombre de paramètres ça n’étais qu'une remarque ! Surtout que ça fait perdre beaucoup de points pour pas grand chose.

  7. #7
    Membre Expert
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Par défaut
    Citation Envoyé par rubisom Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (b <= 0)
       str2[b - 1] = '0';
    !!!
    Tu écris quelques part où tu ne devrais pas.

    Pour le chiffre manquant, tu te trouves dans cette configuration :
    a + b + retenue = 1, avec a == b == 0

    Dans le cas de 999 + 1, tu fais 3 itérations; hors le résultat peut contenir (et ici, contient) 4 chiffres, il faut faire une itération supplémentaire. (Tu auras donc 0 + 0 + retenue == 1 pour cette 4eme itération).

    Je te conseille de stocker tes nombres à l'envers (1234 serait stocké sous la forme "4321"); ça rend les choses plus simples. De même travailles exclusivement avec des entiers, ne t’embête pas avec la conversion 0 <-> '0' à chaque étape.
    Fait la conversion une fois quand tu crée tes nombres à partir de chaines de caractères, et une 2eme fois lors de l'affichage, pour les calculs garde seulement des entiers, c'est plus simple.

    Un exemple, loin d'être parfait, mais fonctionnel, stockant chaque chiffre sur 4 bits.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
     
    #ifndef max
    #define max(a,b) (a > b ? a: b)
    #endif
     
    typedef struct {
    	int size;
    	unsigned char *data;
    } Number;
     
    Number makeNumber(char const* str) {
    	int len = strlen(str);
    	int c = len / 2 + (len & 1);
     
    	Number ret;
    	ret.size = len;
    	ret.data = malloc(c);
    	assert(ret.data);
    	memset(ret.data, 0, c);
     
    	int i = 0;
    	for (--len; len >= 0; --len, ++i) {
    		unsigned char n = (unsigned char)(str[len] - '0');
    		assert(n >= 0 && n <= 9);
     
    		ret.data[i / 2] |= (n << ((i & 1) * 4));
    	}
     
    	return ret;
    }
     
    unsigned char Number_extract(Number const* this, int n) {
    	assert(this);
     
    	return n >= this->size ? 0 : ((this->data[n / 2] >> ((n & 1) * 4)) & 0xF);
    }
     
    Number Number_add(Number const* lhs, Number const* rhs) {
    	assert(lhs);
    	assert(rhs);
     
    	int targetSize = max(lhs->size, rhs->size) + 1;
    	if (targetSize & 1) {
    		++targetSize;
    	}
    	int targetCap = targetSize / 2;
     
    	Number ret;
    	ret.data = malloc(targetCap);
    	assert(ret.data);
    	memset(ret.data, 0, targetCap);
     
    	int carry = 0, i = 0;
    	unsigned char result;
    	for (; i<targetSize; ++i) {
    		result = Number_extract(lhs, i) + Number_extract(rhs, i) + carry;
     
    		carry = result > 9;
    		result -= 10 * carry;
     
    		ret.data[i / 2] |= (result << ((i & 1) * 4));
    	}
    	ret.size = result ? targetSize : targetSize - 1;
     
    	return ret;
    }
     
    void Number_print(Number const* this) {
    	assert(this);
     
    	int i = this->size - 1;
    	for (; i >= 0; --i) {
    		printf("%c", (char)(Number_extract(this, i) + '0'));
    	}
    }
     
    int main() {
     
    	Number a = makeNumber("9998");
    	Number b = makeNumber("2");
     
    	Number c = Number_add(&a, &b);
    	Number_print(&c);
     
    	return 0;
    }

Discussions similaires

  1. Réponses: 4
    Dernier message: 01/01/2010, 20h25
  2. division nombre infini
    Par saturn1 dans le forum Algorithmes et structures de données
    Réponses: 3
    Dernier message: 28/10/2009, 21h47
  3. Algo de division et modul sur nombres infinis
    Par NeoKript dans le forum Débuter
    Réponses: 8
    Dernier message: 02/11/2008, 21h06
  4. [AJAX] Code capable de gérer un nombre infini de fonctions
    Par Orvinfait dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 26/08/2008, 10h17
  5. Nombre infini en C?
    Par vdumont dans le forum C
    Réponses: 4
    Dernier message: 23/10/2006, 18h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo