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 :

convertir double en int64


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juin 2007
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Juin 2007
    Messages : 41
    Par défaut convertir double en int64(continued)
    salut ;
    comment convertir un double en int64 avec le langage C sachant que:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    struct int64
    {
        unsigned int LSW;
        unsigned int MSW;
    };
    Merci par avance

  2. #2
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Par défaut
    J'ai une solution qui n'est pas simple :
    Rappelons d'abord le codage le codage des floats en C:
    Le codage d'un nombre est inspiré de la notation scientifique comme -1.5 × 10+3. Chaque nombre est décomposé en trois parties : signe, exposant et mantisse. Le signe est codé par le bit de poids fort. Ensuite un certain nombre de bits sont consacrés à l'exposant et le reste à la mantisse. La table ci-dessous donne le nombre de bits de chacun des éléments dans les différents formats.
    Encodage Signe s Exposant e Mantisse m Valeur d'un nombre
    Simple précision 32 bits 1 bit 8 bits 1≤e≤254 23 bits (-1)s× 1.m ×2e-127
    Double précision 64 bits 1 bit 11 bits 1≤e≤2046 52 bits (-1)s× 1.m ×2e-1023
    Précision étendue 80 bits 1 bit 15 bits 1≤e≤32766 64 bits (-1)s× 1.m ×2e-16383

    Dans la table ci-dessus, la formule 1.m doit être interprétée de la façon suivante. Si les bits de la mantisse sont b1b2…bn, on a

    1.m = 1 + b1/2 + b2/22 + b3/23 + … + bn/2n

    Soit l'exemple en simple précision 101111110101100…0 (0xbf580000 en hexadécimal). Il se décompose en le signe s = 1, l'exposant e = 01111110 = (126)10 et la mantisse m = 1010100…0. La valeur de 1.m = 1+1/2+1/8+1/16 = 1,6875. La valeur du nombre est donc -1,6875 × 2-1 = -0,84375.
    Il me semble que votre problème n'a de sens que pour les GRANDS double
    Je fais l'hypothèse simplificatrice que le signe est >0 donc le bit de signe = 0
    je fais aussi l'hypothèse que l'exposant e est positif et >52
    La première étape consiste à multiplier la mantisse par 2^52 et à répartir le résultat sur LSW et MSW, il suffir pour cela de glisser les 32 bits de poids faible sur LSW et les 20 bits de poids fort sur MSW.
    Il reste à multiplier le resultat par 2^(e-52)
    On va le faire par itération de la manière suivante.
    Il suffit de savoir faire une multiplication par 2 sur le couple LSW MSW
    Voici le processus:
    1) regarder si LSW <= 2^31 (consultation du bit de poids fort)
    Si c'est le cas tomber le bit de poids fort ce qui correspond à une soustraction de 2^31
    2) multiplier par 2 LSW et MSW (simples décalages)
    3) si on a tombé le bit de poids fort en 1) alors ajouter 1 unité à MSW
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  3. #3
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 962
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 962
    Par défaut
    Hja,

    Houla, bien compliqué tout ça.
    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
    struct int64
    {
    unsigned int LSW;
    unsigned int MSW;
    };
     
    int main()
    {
        int64 m64;
        m64.MSW = 2;
        m64.LSW = 10;
        double d = (m64.MSW * 4294967296ULL) + m64.LSW;
        printf("d = %f\n",d);
     
     
        return EXIT_SUCCESS;
    }
    Avec ces valeurs, on doit donc obtenir 2*2^32 + 10 = 8589934602

    et résultat = 8589934602.000000

  4. #4
    Rédacteur
    Avatar de Zavonen
    Profil pro
    Inscrit en
    Novembre 2006
    Messages
    1 772
    Détails du profil
    Informations personnelles :
    Âge : 77
    Localisation : France

    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 772
    Par défaut
    C'est la conversion en sens inverse qui est demandée.
    Ce qu'on trouve est plus important que ce qu'on cherche.
    Maths de base pour les nuls (et les autres...)

  5. #5
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 962
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 962
    Par défaut
    Jie,
    Citation Envoyé par Zavonen
    C'est la conversion en sens inverse qui est demandée.
    Houla, lu trop vite .

  6. #6
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 962
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 962
    Par défaut
    Sio,

    Avec un petit coup d'assembleur, c'est plus court.

    En syntaxe AT&T (pour GCC)
    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
    struct myint64
    {
        unsigned int LSW;
        unsigned int MSW;
    };
     
    void doubleToMy64(double *d, myint64 *r)
    {
        __asm__ (
            "movl %0,%%eax\t\n"
            "fldl (%%eax)\t\n"
            "movl %1,%%eax\t\n"
            "fistpq (%%eax)"
            :
            : "m" (d), "m" (r)
            : "%eax"
        );
    }
     
    int main()
    {
        myint64 m64;
    //    double d = 8589934602.0L; // 2^32*2 + 10
    //    double d = 536870912987.0L; // 2^32*125 + 987
        double d = 387086051008789.0L; // 2^32*90125 + 2123456789
        doubleToMy64(&d,&m64);
        printf("d = %f, MSW = %u, LSW = %u\n",d,m64.MSW,m64.LSW);
     
     
        return EXIT_SUCCESS;
    }
    Résultat :
    d = 387086051008789.000000, MSW = 90125, LSW = 2123456789

    En syntaxe Intel (pour VC++), la fonction devient (pas testé, car je n'ai pas VC++ !)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void doubleToMy64(double *d, myint64 *r)
    {
        __asm {
            mov eax, d
            fld qword ptr [eax]
            mov eax, r
            fistp qword ptr [eax]
        }
    }

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

Discussions similaires

  1. Convertir double en int
    Par Hafa10 dans le forum Débuter avec Java
    Réponses: 3
    Dernier message: 27/05/2015, 14h25
  2. Convertir (double) 1.0 en (int) 1
    Par easypixels dans le forum Général Java
    Réponses: 6
    Dernier message: 28/10/2014, 19h26
  3. Convertir double en int
    Par emna hakem dans le forum C#
    Réponses: 3
    Dernier message: 10/03/2011, 13h03
  4. convertir double en int toujours à zero
    Par royreal dans le forum C#
    Réponses: 3
    Dernier message: 04/04/2010, 16h35
  5. [LG]Convertir le type double en string
    Par @tom@ dans le forum Langage
    Réponses: 8
    Dernier message: 18/01/2004, 19h20

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