Bonjour,
j'ai un :
double x;
je récupère sa première moitié dans un float :
float a = (float)x;
je cherche à récupéer la 2ème moitié, je fais comment ??
Merci bcp
Version imprimable
Bonjour,
j'ai un :
double x;
je récupère sa première moitié dans un float :
float a = (float)x;
je cherche à récupéer la 2ème moitié, je fais comment ??
Merci bcp
J'ai du mal à comprendre l'idée que tu as derrière la tête. Pouquoi veux tu séparrer un Double en deux float?
Ça ne me parait compliqué et sans intérêt.
le double il est codé sur 8 octets le float est sur 4, j'ai besoin de mettre chaque 4 octets du double à part
C'est d'ailleurs impossible de le faire de manière exacte en effet:
les floats ont 23 bits pour la mantisse, 8 bits pour l'exposant et 1 bit pour le signe alors que les doubles ont 52 bits pour la mantisse, 11 bits pour l'exposant, 1 bit pour le signe.
Dont même avec 2 float, tu ne pourras pas stoker toute la mantisse.
Code:
1
2
3
4
5
6
7 long xL = Double.doubleToLongBits(x); int xI1 = (int)xL; int xI2 = (int)(xL >> 32); float y1 = Float.intBitsToFloat(xI1); float y2 = Float.intBitsToFloat(xI2);
Mais comme on a déjà dit, faire du C++ en Java, ça ne vas pas super bien...
en C++ c'est possible en utilisant un pointeur :
mais en java ????Code:
1
2
3
4
5
6
7
8 double x; float a, b; float *ip; ip = (float)&x; a = (*ip); ++ip; b = (*ip);
Si c'est juste séparer en plusieurs parties sans te soucier de la valeur il est plus simple de passer par doubleToLongBits() qui te retournera un long. Tu peux ainsi découper le découper facilement en morceaux avec un masque et des décalages binaire.
Tu peux ensuite reconstruire le double avec longBitsToDouble()
En suivant ton exemple, ca donnerait:
Je pense que tu peux garder le résultat dans des int car comme les float ils font 32 bit. De toute façon les valeurs de tels flottants n'auraient absolument aucun sens.Code:
1
2
3
4 double x; long l = Double.doubleToLongBits(x); int a = ( l >> 32) & 0xFFFFFFFF; int b = l & 0xFFFFFFFF;
Mais si tu tiens tout de même à avoir du float, tu peux utiliser Float.intBitsToFloat()
Même en c++, ce code est erroné. Le choix des type a et b est erroné et ils ne stockeront jamais, dans ce cas, un float qui aura du sens par rapport à x. De plus, rien dans les spécification c++ ne te dit que le float est la moitié (en taille bits) d'un double. Tout ce que dit la spécification C++ c'est que taille(float)<=taille(double)<=taille(long double).
Si ce code fonctionne chez toi, c'est jsute parce que tu as la chance d'utiliser un compilateur/une architecture utilisant une taille de float deux fois inférieure à la taille d'un double.
Rien ne sert d'essayer de transcrire du C++ en java et encore moins du C++ erroné. La solution de uther d'ailleurs est la plus propre pour récupérer et manipuler les bits d'un double.
le >> déplace tous les bits du nombre de 32 positions vers la droite(comme en C). Ainsi les 4 octets de poids vont remplacer les octets de poids faible.
Le "& 0xFFFFFFFF" était pour effacer les 4 octets de poids fort mais en y réfléchissant, c'est inutile vu que la conversion du long(8 octets) en int(4 octets), les fait automatiquement disparaitre.
Le code proposé par dingoth est donc en effet plus simple:
Code:
1
2
3
4 long xL = Double.doubleToLongBits(x); int xI1 = (int)xL; int xI2 = (int)(xL >> 32);
Normalement avec ce code, il ne devrait pas y avoir de perte de précision. Es-tu sur que ce n'est pas ta fonction d'affichage fait un d'arrondi?
Tu as du faire une erreur en réassambant les deux parties. Je n'ai pas pas d'écart avec ce code:
Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 public static void main(String[] args) { double x=272008320221930670000000.000000; //séparation long l = Double.doubleToLongBits(x); int a = (int)( l >> 32); int b = (int) l ; //recolage long l2 = ((long)a<<32)|(b&0xFFFFFFFFL); double y=Double.longBitsToDouble(l2); System.out.println("x -> " + x); System.out.println("y -> " + y); }
finalement je pense que c'est uniquement du à l'affichage.
Merci beaucoup pour l'aide.
Maintenant quand j'essais avec un Integer et short
la w2 donne la bonne valeur contrairement au w1, une idée ???Code:
1
2
3
4 Integer x = 214748364; short w1 = x.shortValue(); short w2 = (short)(x >> 16);
Je pense qu'on s'est mal compris. moi je cherche à récupérer les 2 premiers octets d'un int dans un short, et les 2 derniers dans un autre short, la ligne
me récupère bel et bien les 2 derniers octets, maisCode:short w2 = (short)(x >> 16)
ne me donne pas le bon résultat des 2 premiers octetsCode:short w1 = (short)x;
Le code que tu as posté est correct. Le problème doit venir de la façon dont tu utilises w1 et w2.
Je penses en effet que tu as un problème de copnversion. Il faut savoir qu'en Java, les type de taille inférieure à int sont automatiquement convertis en int quand on fait des opération avec. Et comme tous les nombre sont signés, la convertion peut surprendre:
- w2 vaut 0xcccc. C'est un nombre négatif(isupérieu ou égal à 0x8000) et il est donc converti en 0xffffcccc.
- w1 vaut 0xccc. C'est un nombre positif(inférieur à 0x8000) et il est convertie en 0x00000ccc
Ceci expliquerait pourquoi tu ne vois pas de problème avec w1.
Si tu veux une conversion en entier sans tenir compte du signe utilises (w1 & 0xFFFF) et (w2 & 0xFFFF).
je suis un peu perdu avec les 0x... mais j'ai compris ton idée.
donc pour corriger mon code et faire la conversion en ignorant le signe je met :
??? je me trompe surement car il n'y a rien eu de changé dans mon résultatCode:
1
2
3
4 int x = 2147483646; short w1 = (short)(x & 0xFFFF); short w2 = (short)(x >> 16);