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 :

Problème de résultat d'une opération mathématique


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Mars 2009
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 13
    Par défaut Problème de résultat d'une opération mathématique
    Bonjour,

    Je me lance dans la programmation en C sur microcontrôleur et je rencontre un problème d'ordre bizarre, voire inexpliqué.

    Voici le code qui pose un soucis :
    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
     
    void Display_Cursor(signed int lat, signed int lon) {
      unsigned char latitude_y, longitude_x;
     
      //Latitude and Longitude scaling for 128x64 display:
      //Latitude: Input range is -90 to 90 degrees
      //Longitude: Input range is -180 to 180 degrees
      latitude_y = ((61*(90-lat))/180)+1;
      longitude_x = ((125*(lon+180))/360)+1;
     
      //Cursor drawing:
      Glcd_H_Line(0, 127, latitude_y, 2);
      Glcd_V_Line(0, 63, longitude_x, 2);
     
      //Display latitude and longitude "translation" to fit on the screen
      IntToStr(latitude_y,dispLatStr);
      IntToStr(longitude_x,dispLonStr);
      Glcd_Write_Text(dispLatStr,0,6,1);
      Glcd_Write_Text(dispLonStr,0,7,1);
     
      //Blinking
      Delay_ms(500);
      Glcd_Fill(0x00);
    }
    Le problème c'est que la ligne verticale (longitude) ne s'affiche pas car elle est hors de l'écran (position longitude=196 sur un écran de 128 pixels). Cela peut être solutionné en affectant la valeur au paramètre "lon".
    Pour résumer :
    - Si le paramètre "lon" de la fonction est utilisé tel quel (sa valeur est de 166 à l'appel de la fonction), le résultat du calcul est faux.
    - Si je met "lon = 166;" dans la fonction, le résultat est correct.

    Ma question est simple : comment se fait-il qu'avec une même valeur, le résultat d'un calcul puisse être différent ?
    Question bonus : pourquoi ce problème n'est pas rencontré pour le calcul de la latitude ?

    Si vous avez besoin de plus de renseignements, n'hésitez pas.
    Merci d'avance pour vos réponses.

  2. #2
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 496
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 496
    Billets dans le blog
    1
    Par défaut
    Quel est ton micro-contrôleur (µC) ? Est-ce un µC 8 bits ?

    Tu peux nous dire la valeur rendue par sizeof int ?

  3. #3
    Membre averti
    Inscrit en
    Mars 2009
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 13
    Par défaut
    Effectivement, j'ai omis les infos d'environnement. Les voici donc :
    IDE : MikroC
    µC : 8bit 18F4250.

    Pour ce qui est du siezof int, je vous répond demain, car je n'ai pas la carte de dev sous la main.

  4. #4
    Membre Expert
    Avatar de skeud
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Juin 2011
    Messages
    1 091
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2011
    Messages : 1 091
    Billets dans le blog
    1
    Par défaut
    C'est un µC en 8 bit du coup lors de ton calcul:
    125*(166+180)=43250.
    Or 43250 = 1010100011110010 donc pour pouvoir stocker ce nombre, il te faut un espace de 16bit (sur un pc, ça passe nikel comme c'est du 32 ou 64bit).

    Par contre sur ton µC c'est du 8bit donc tu dépasse ta valeur INT_MAX. C'est donc normal que ton calcul soit faux.

    Pour la solution, je n'ais pas assez de connaissances sur ce genre de programmation pour te répondre, mais tu as une piste .

  5. #5
    Membre chevronné
    Inscrit en
    Décembre 2010
    Messages
    290
    Détails du profil
    Informations forums :
    Inscription : Décembre 2010
    Messages : 290
    Par défaut
    Si Bktero et skeud ont raison (et je pense qu'ils ont raison), alors il reste une question sans réponse :

    comment se fait-il qu'avec une même valeur, le résultat d'un calcul puisse être différent ?
    Ma théorie, c'est que si tu écris la valeur de variable directement dans le source de la fonction, alors d'une certaine manière, pour le compilateur, ce n'est plus une variable, c'est une constante.
    Il peut donc remplacer ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    longitude_x = ((125*(lon+180))/360)+1;
    par ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    longitude_x = ((125*(166+180))/360)+1;
    et donc, comme optimisation, virer le calcul et coder directement la valeur résultante dans longitude_x.
    Mais ton compilateur ne souffre pas des mêmes problèmes de précision, donc la valeur résultante est "juste".

  6. #6
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 501
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 501
    Par défaut
    Hello à tous !

    Citation Envoyé par Porkipic Voir le message
    Ma question est simple : comment se fait-il qu'avec une même valeur, le résultat d'un calcul puisse être différent ?
    Il faudrait le code du niveau juste au-dessus pour voir comment ton paramètre est transmis. Et d'une manière générale, il faudrait vérifier au debugger que la valeur arrive bien intacte au début du code de ta fonction.

    Question bonus : pourquoi ce problème n'est pas rencontré pour le calcul de la latitude ?
    Parce que la formule n'est pas la même non plus et qu'à ce stade, le mystère n'est pas élucidé.

    Citation Envoyé par skeud Voir le message
    C'est un µC en 8 bit du coup lors de ton calcul:
    Pendant très longtemps, on a travaillé avec des machines 8 bits, en temps qu'ordinateur de bureau (notamment les Thomson dans les écoles) et on manipulait des nombres plus larges. Heureusement ! La seule différence est que le calcul se fait en plusieurs étapes plutôt que tenir en une seule instruction assembleur, ce qui a d'ailleurs favorisé l'abandon de sa pratique au profit du C. Mais le C stipule en principe qu'un short int doit mesurer au moins 16 bits et qu'un int ne peut être moins large. Il est possible que sur certaines plateformes, ces valeurs soit revues à la baisse mais c'est très peu probable sans raison valable et ça n'a pas lieu d'être sur un micro-contrôleur récent et grand public comme le PIC 18Fxxxx.

    125*(166+180)=43250.
    Or 43250 = 1010100011110010 donc pour pouvoir stocker ce nombre, il te faut un espace de 16bit (sur un pc, ça passe nikel comme c'est du 32 ou 64bit).
    À mon avis, c'est surtout ça le problème : on ne peut stocker 43250 que sur 16 bits non signés ! Le type int naturel est signé par défaut et c'est également ce format qui est utilisé par les arguments de la fonction. Si le format int est sur 16 bits par défaut sur cette cible, il n'y a pas de raison que le compilateur le promeuve automatiquement à un format plus grand. D'où la question très pertinente de Bktero.

    Citation Envoyé par phi1981 Voir le message
    Ma théorie, c'est que si tu écris la valeur de variable directement dans le source de la fonction, alors d'une certaine manière, pour le compilateur, ce n'est plus une variable, c'est une constante.
    Il peut donc remplacer ce code […] et donc, comme optimisation, virer le calcul et coder directement la valeur résultante dans longitude_x. Mais ton compilateur ne souffre pas des mêmes problèmes de précision, donc la valeur résultante est "juste".
    Très pertinent également, et c'est probablement pour cette raison que le calcul fonctionne dans ce cas si la « panne » ne vient pas d'une erreur de transmission en amont.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MySQL] [SQL] problème affichage résultat d'une requête
    Par mitmit dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 30/04/2007, 11h14
  2. Réponses: 19
    Dernier message: 21/11/2006, 11h57
  3. Réponses: 5
    Dernier message: 17/06/2006, 12h33
  4. [MySQL] problème de résultat avec une requête
    Par jexl dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 29/03/2006, 23h23
  5. [SQL] Problème de résultat avec une requête
    Par raptorman dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 04/01/2006, 17h16

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