salut ;
comment convertir un double en int64 avec le langage C sachant que:
Merci par avance
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 struct int64 { unsigned int LSW; unsigned int MSW; };
salut ;
comment convertir un double en int64 avec le langage C sachant que:
Merci par avance
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 struct int64 { unsigned int LSW; unsigned int MSW; };
J'ai une solution qui n'est pas simple :
Rappelons d'abord le codage le codage des floats en C:
Il me semble que votre problème n'a de sens que pour les GRANDS doubleLe 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.
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...)
Hja,
Houla, bien compliqué tout ça.
Avec ces valeurs, on doit donc obtenir 2*2^32 + 10 = 8589934602
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; }
et résultat = 8589934602.000000![]()
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...)
Jie,
Houla, lu trop vite .Envoyé par Zavonen
![]()
Sio,
Avec un petit coup d'assembleur, c'est plus court.
En syntaxe AT&T (pour GCC)
Résultat :
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; }
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] } }
Partager