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 :

Conversion virgule fixe - virgule flottante


Sujet :

C

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9
    Points : 12
    Points
    12
    Par défaut Conversion virgule fixe - virgule flottante
    Salut, S'il-vous-plaît aidez moi, je ne sais même pas comment commencer cet exercice :

    Voila le texte de l'exercice :

    Soit la représentation en virgule fixe 1.15 en complément à 2 sur 16 bits, où la virgule est à droite du bit de poids fort et où les 15 bits à droite de la virgule correspondent aux puissances 2-i. Cette représentation permet de représenter des nombres entre -1 et 1-2-15.

    Écrire la fonction C qui permet de convertir un nombre virgule fixe 1.15 en nombre flottant simple précision pour pouvoir afficher sa valeur à l’aide des formats d’impression flottant %f ou %d de C.

    Pour tester la conversion virgule fixe vers virgule flottante, on entrera un nombre signé 16 bits (short) et l’on vérifiera son interprétation 1.15 après conversion en flottant.

    Aide :

    Le programme C suivant permet d’afficher le contenu hexadécimal du codage d’une variable de type float : ca et &a correspondent à la même adresse. a est la variable flottante, et *ca est le contenu de la même variable, mais interprété comme un entier et affiché en hexadécimal (%x).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    main()
    {
              float a=10.0;
              int *ca;
              ca = (int *)&a;
              printf("codage du flottant = %x \n", *ca);
    }

  2. #2
    Membre expérimenté

    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2011
    Messages
    685
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2011
    Messages : 685
    Points : 1 418
    Points
    1 418
    Par défaut
    relis tes cours de mathématiques discrètes : la réponse est dedans...

    Sinon les conversions de ce type de mémoire il y a une méthode "manuelle" pour le faire mais c'est loin... complément à 2 ça veut dire que tu n'aura que les valeurs 0 et 1 possible non ?

    donc déjà d'un coté tu traduit la valeur après la virgule en base 10, ensuite l'autre à laquelle tu ajoutes ce que tu as déjà traduit. Sinon, y'a tout un mécanisme à suivre pour ce genre de conversion, tu dois l'avoir dans ton cours.

    Si tu peux pas le faire déjà par toi-même, c'est clair que ça va être dur de l'apprendre à ton ordinateur.

    Cordialement,

  3. #3
    Futur Membre du Club
    Femme Profil pro
    n.d.
    Inscrit en
    Décembre 2011
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Autre

    Informations professionnelles :
    Activité : n.d.

    Informations forums :
    Inscription : Décembre 2011
    Messages : 5
    Points : 8
    Points
    8
    Par défaut
    pour la conversion decimal virgule fixe vers binaire virgule flottant type(654,123):

    tu prends l entier que tu transformes en binaire par division euclidienne en gardant a chaque etape le restant de l operation:

    654:2=327 reste 0
    327:2=163 reste 1
    163:2=81 reste 1
    81:2=40 reste1
    40:2=20 reste 0
    20:2=10 reste 0
    10:2=5 reste 0
    5:2=2 reste1
    2:2=1 reste 0
    1==>reste 1

    tu lis ca de bas en haut la representation binaire de 654=1010001110

    pour la partie fractionnaire 0.123 tu gardes l entier d une multiplication par 2 (toujours de la partie fractionnaire)de manieres successives


    0.123*2=0.246 entier=0
    0.246*2=0.492 entier=0
    0.492*2=0.984 entier=0
    0.984*2=1.968 entier=1
    0.968*2=1.936 entier=1
    etc etc etc

    tu lis le resultat de haut en bas 0.123=00011....
    tu assembles le tout 1010001110,00011....
    tu decale l ensemble (premier bit significatif) pour que tout a part l entier soit deriere la virgule et tu compte le decalage
    resultat 1,01000111000011 decalage =-9 (attention si 0.00001 alors decalage="+"5)

    alors un binaire virgule flotant se compose en 3 parties bit de signe,exposant decalé,mantisse

    le bit de signe 0 si ton chiffre est positif 1 si il est negatif

    exposant decalé on le calcul avec le decalage avec la formule e-d

    d= ton decalage (-9)
    e=(2^(n-1) )-1 n etant le nombre de bit attribue a l exposant

    16bit=5bit d exposant
    32bit=8bit d exposant
    64bit=11bit d exposant

    ça c est standar

    donc 2^(5-1)-1=2^4 -1 = 16-1=15
    e-d= 15--9=24

    tu transformes cela en binaire par div euclidienne comme tantot =11000
    (ex=si ton expo =4 alors =00100 )tu dois garder 5 bit d exposant pour le 16 bit

    ensuite tu reprends ta converssion binaire de tantot 1,01000111000011

    tu retire l entier ,01000111000011 et tu prends le nombre de bit necessaire pour completer tes 16 bit de gauche a droite

    resultat : 1 bit de signe 0 654,123 est positif
    ton exposant decale de 5 bit 11000
    tu complete avec 10 bit de mantisse 0100011100


    tu assemble le tout pour avoir : 0 11000 0100011100



    pour ton prog en c tu cree dux tableau en "int"un pour les entier
    un pour les fractionnaires

    un if pour voir si c est un positif ou pas donne 0 ou 1 a une variable

    pour les entier
    dans une boucle for ou un do while tu fais un modulo 2 de ta variable et tu stocke le resultat dans ton tableau en incrementant la position du tableau
    ce qui te donnera en plus le nombre d element

    apres pour les fractionnaires operations de tantot (voir plus haut)

    dans une boucle for ou un do while selon preference

    tu stockes les entiers et si superieurs a 1(1.256) tu soustrais 1

    avant de recommencer

    et tu stocke en incrementant ton tableau

    tu fais une boucle do while dans ton tableau d entier en partant du nombre de chiffre obtenu tantot jusqua ce qu il trouve un 1 d0{var=var-1;}while(T_entier[var]!=1 && var>=0)

    quand il sort var est le nombre de bit en entier a partir du premier bit significatif s il ne trouve pas meme ope dans l autre sens dans letableaufractionnaire

    var sera donc egal a ton decalage+1

    tu t en sers pour calculer l exposant

    soit tu emploies un troisieme tableau pour le stocker soit tu empruntes de la memoire d ans un de tes tableaux existant

    puis un petit cls

    printf("%d",signe);
    for(i=emplacement de ton exposant;i<=emplacement de ton exposant +5;i++)
    printf("%d",Tab[i])

    puis une derniere boucle for pour ta mantisse de la meme maniere que les precedants


    j espere t avoir aidé je sais pas si c est la meilleur methode mais c est sur qu elle marche

    je suis desolé pour l autographe mais j aivite écrit cela avant d y aller j ai pas eu le temps de corriger les fautes

    ps:j ai une feuille excell qui fais le calcul dis moi si tu la veu pour verifier ton programme

    pps: si ca va toujours pas tu me dis je t enverrai le code en c avec full commentaire



    pppps: si tu veu la jouer a l epat propose un choix du nombre de bit 8,16,32,64,80,128 tu trouvera les caracteristique de chacun sur internet en tapant standard IEEE754

    et propose aussi la conversion final en octal ou en hexa

    c est un travail minime une fois que tu l'as fais pour 16 bit


    ppppppps:Erreurs d'arrondis
    Voici quelques exemples catastrophiques dus à des erreurs d'arrondis.
    Le 25 février 1991, une batterie américaine de missiles Patriot, a échoué dans
    l'interception d'un missile Scud irakien. Le Scud a frappé un baraquement de l'armée
    américaine et a tué 28 soldats. La commission d'enquête a conclu à un calcul incorrect du
    temps de parcours, dû à un problème d'arrondi. Les nombres étaient représentés en
    virgule fixe sur 24 bits. Le temps était compté par l'horloge interne du système en 1/10
    de seconde. Malheureusement, 1/10 n'a pas d'écriture finie dans le système binaire : 1/10
    = 0,110 = 0,0001100110011001100110011...2. L'ordinateur de bord arrondissait 1/10 à 24
    chiffres, d'où une petite erreur dans le décompte du temps pour chaque 1/10 de seconde.
    Au moment de l'attaque, la batterie de missile Patriot était allumée depuis environ 100
    heures, ce qui avait entraîné une accumulation des erreurs d'arrondi de 0,34 s.. Pendant
    ce temps, un missile Scud parcourt environ 500 m, ce qui explique que le Patriot soit
    passé à côté de sa cible.
    Le 4 juin 1996, une fusée Ariane 5 a explosé 40 secondes après l'allumage. La fusée et son
    chargement avaient coûté 500 millions de dollars. La commission d'enquête a rendu son
    rapport au bout de deux semaines. Il s'agissait d'une erreur de programmation dans le
    système inertiel de référence. À un moment donné, un nombre codé en virgule flottante
    sur 64 bits (qui représentait la vitesse horizontale de la fusée par rapport à la plate-forme
    de tir) était converti en un entier sur 16 bits. Malheureusement, le nombre en question
    était plus grand que 32768, le plus grand entier que l'on peut coder sur 16 bits, et la
    conversion a été incorrecte.
    Source : http://www.apprendre-en-ligne.net/bl...emes-d-arrondi


    faut vraiment que j y aille encore desole pour la presentation

  4. #4
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Décembre 2011
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9
    Points : 12
    Points
    12
    Par défaut
    Et voila désolé pour le retard:


    // Par Kebadji Billel



    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
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    #include <cstdlib>
    #include <iostream>
    #include <cstdlib>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #define br printf("\n")
     
     
     
    double cast_int(float nombre)
    { double fractpart, intpart;
      fractpart = modf (nombre , &intpart);
      return (intpart);
     
    }
     
    double cast_fract(float nombre)
    { double fractpart, intpart;
      fractpart = modf (nombre , &intpart);   
      return (fractpart);
    }
     
     
    int main ()
    {float nombre;
      double verif,intpart,fractpart  ;
      char frac[100];
      char buffer [10];
      char afficher[16];
      int x=0,i=0,j=0,exp = 0;
      int choix = 0;  
      int i_Afficher = 0;
     
      printf("Entrer le nombre\t");
      scanf("%f",&nombre);
     
      if (nombre>0)afficher[i_Afficher]='0';
      else{ afficher[i_Afficher]='1'; nombre = -nombre;}
     
     
      intpart=cast_int(nombre);
      fractpart=cast_fract(nombre);
     
      /***************************/
     
     
      i_Afficher = 6;
     
      j=(int)intpart;
      itoa (j,buffer,2);
      printf ("binary: %s",buffer);
     
      if (j>0) choix = 0 ; // partie entier n'est pas Null
      else choix = 1;     // partie entier est pas Null
      /***************************/
      printf(",");
        /*************************/
     while (fractpart != 0)
          {
          fractpart= fractpart * 2;
     
                 verif= cast_int(fractpart);
                // printf("%lf",verif);
                  if (verif == 1)
                     {       frac[x]='1';
                             x++;
                             fractpart = cast_fract(fractpart);
                             //printf("%lf\t",result);
                             }
                  else {frac[x]='0';
                  //fractpart = cast_fract(fractpart);
                         x++;}
     
     
                  }
     
      for (i = 0 ; i < x ; i++)
        {
            printf("%c", frac[i]);
        }br;
        /*************************/
     
     if (choix == 0)
        {
         int stop = 0;
         exp = 0;
         i = 1;
         while (i_Afficher <16 && stop == 0 && i<10)
        { if (buffer[i] == '1') afficher[i_Afficher] = '1';
         else if (buffer[i] == '0') afficher[i_Afficher] = '0';
         else {stop = 1; i_Afficher --;exp --;}
         i++; i_Afficher ++; exp ++;}
     
         //ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
     
           stop = 0;
           i=0;
     
            while (i_Afficher <16 && stop == 0 && i<100)
     
        { if (frac[i] == '1') afficher[i_Afficher] = '1';
         else if (frac[i] == '0') afficher[i_Afficher] = '0';
         else {stop = 1; i_Afficher --;}
         i++; i_Afficher ++;}
     
     
         //ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt
         }
    else     
         {
             i = 0;
             exp =0;
             int stop = 0;
     
     
           while (stop == 0 && i<100)  
             {   if (frac [i] == '0'){exp ++;i++;}
                 else if (frac[i] == '1'){exp ++; i++; stop = 1;}
                 else stop = 1;
                      }
             stop = 0;
     
            while (i_Afficher <16 && stop == 0 && i<100)
     
        { if (frac[i] == '1') afficher[i_Afficher] = '1';
         else if (frac[i] == '0') afficher[i_Afficher] = '0';
         else {stop = 1; i_Afficher --;}
         i++; i_Afficher ++;}
     
         exp = -exp;
         }
     
     
     
     
       while (i_Afficher <16){
       afficher[i_Afficher] = '0'; 
       i_Afficher ++;
    }      
     
    j=0;
    i=0;
    char t_Exp [10];
    exp = exp + 15;
     j=(int)exp;
      itoa (j,t_Exp,2);
      if(j<=15)
      {
               for(i=4;i>0;i--)
               {
                  t_Exp[i] = t_Exp[i-1];
               }
               t_Exp[0]='0';
               t_Exp[5]='\0';
      }
     
     j=0;
    for (i=1;i<6;i++)
    {
        afficher[i] = t_Exp[j];
        j++;
    }
     
    afficher [16] = '\0';
    printf("\n Afficher = %s\n exp = %d\n" , afficher, exp);   
     
     
     
      system("pause");
    }

  5. #5
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Je ne comprend pas l'utilité de tous ces discours (ou j'ai mal compris la question) :
    - Si on suppose que les fixes sont sur 16 bits en complément à 2 et que les short sont sur 16 bits en complément à 2, la conversion me semble élémentaire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    float convertFix2Float(short val)
    {
      return val/32768.0;
    }
    - Les choses se compliquent un peu si les entiers peuvent être dans un autre code que le complément à 2 alors que les fixes sont en complément à 2.
    On peut calculer la valeur absolue du nombre, dont la représentation sera identique pour les 3 possibilités de codage des entiers, puis corriger le résultat en fonction du signe du nombre en virgule fixe.
    La condition val<0 teste dans les trois cas le bit en poids fort (le bit de signe) de val. On sait que le fixe est en complément à 2 donc on obtient sa valeur absolue par ~val+1.
    Par exemple :
    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
    #include <stdio.h>
    #include <limits.h>
    typedef short Fix ;         // type de support d'un fixe
    #define FIX_MAX SHRT_MAX    // extension du support : soit 32767 pour des short de 16 bits
    //typedef int Fix ;         // pour des fixes plus grand
    //#define FIX_MAX INT_MAX
    //------------------------------------
    float convertFix2Float(Fix val)
    {
      double f ;
      int neg = val<0;                // déterminer le signe
      if(neg) val= ~val+1;            // prendre la valeur absolue : val est en C2
      f= val/((double)FIX_MAX+1.0);   // ne pas calculer FIX_MAX+1 en entier :
                                      // il n'est pas sûr que  FIX_MAX+1 tienne sur un int
      return neg ? -f : f;            // corriger le résultat en fonction du signe
    }
    //-------------------------------- Exemple
    int main(void)
    {
      Fix i = 0xa100;
      float f = convertFix2Float(i);
      printf("%.10f\n" , f);
      i = 0x5f00;
      f = convertFix2Float(i);
      printf("%.10f\n" , f);
      return 0;
    }

Discussions similaires

  1. rendre un nombre de virgule flottante en virgule fixe
    Par mitnick2006 dans le forum Général Java
    Réponses: 3
    Dernier message: 15/08/2008, 21h44
  2. Comment fixer le nombre de chiffre après la virgule d'un flottant
    Par moon93 dans le forum Général Python
    Réponses: 1
    Dernier message: 15/06/2007, 16h49
  3. virgule fixe en java
    Par Elendhil dans le forum Général Java
    Réponses: 3
    Dernier message: 24/05/2007, 23h02
  4. [BigDecimal][nbDigits] conversions chiffres apres virgule
    Par jeb001 dans le forum API standards et tierces
    Réponses: 12
    Dernier message: 11/10/2006, 14h08
  5. Chiffre a Virgule Fixe
    Par garybaldi dans le forum C
    Réponses: 3
    Dernier message: 21/06/2002, 10h41

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