operations binaire sur un float

operations binaire sur un float - C++ - Programmation

Marsh Posté le 23-10-2005 à 20:58:39    

Bonjour, bon actuellement je veux envoyer des informations via réseau. or on ne peut envoyer que des caractères... Alors j'ai trouvé la parade : à l'aide d'opérations binaire je décompose mon flottant en 4 octets que je convertis en char, je l'envoi par réseau et une fois de l'autre côté je reconvertis mes char en byte que je réassemble et je récupère mon flottant !!! pas mal non ?
  Bon alors en fait j'arrive a le faire avec des short... mais une fois que je passe aux float (ou aux int ) ça marche plus : le compilateur ne veut pas que je fasse des opérations binaire sur ces types... Bon en Java j'avais la méthode : "floatToIntBits(float x)" dans la classe float qui permettait ensuite de le faire mais en C++ je trouve rien de tel quelqu'un aurrait-il une idée a me proposer ?
 
bon pour l'info voilà mon code que je voulais faire :

Citation :


byte rep[4];
void decompose(float f)
{
   rep[0] = (byte)(f & 0xff);
   rep[1] = (byte)(f & 0xff00);
   rep[2] = (byte)(f & 0xff0000);
   rep[3] = (byte)(f & 0xff000000);
}
 
 
float recompose(void)
{
   float f = 0;
   
   f = rep[3];
   f = (f & 0xff) << 24;
   f |= (rep[2] & 0xff) << 16;
   f |= (rep[1] & 0xff) << 8;
   f |= (rep[0] & 0xff);
 
   return f;
}

Reply

Marsh Posté le 23-10-2005 à 20:58:39   

Reply

Marsh Posté le 23-10-2005 à 21:30:35    

pas bon. mets ton float quand un entier non signé de 32bits ou dans un char[]

Reply

Marsh Posté le 23-10-2005 à 21:33:02    

ça ma parait douteux ton truc de "char seulement" mais bon...
 

Code :
  1. /* Convention : sur le réseau c'est du little-endian */
  2. template<typename T>
  3. void swapEndian(T& data)
  4. {
  5. #ifdef BIG_ENDIAN
  6.     char* const p = static_cast<char*>(&data);
  7.     for (int i=0 ; i<sizeof(T)/2 ; i++)
  8.         std::swap(p, p[sizeof(T) - 1 - i]);
  9. #endif
  10. }
  11. void decompose(float f)
  12. {
  13.    swapEndian(f);
  14.    memcpy(rep, &f, sizeof(f));
  15. }
  16. float recompose(void)
  17. {
  18.    float f;
  19.    memcpy(&f, rep, sizeof(f));
  20.    swapEndian(f);
  21.    return f;
  22. }


 
attention à l'endian-dependance et à l'implantation de [i]float. Toutes les archis ne sont pas IEEE-754 et float ne fait pas toujours 32-bits. Avec ce code, si le client est x86 et le serveur MIPS ça risque de pas trop marcher.
 
edit : je t'ai ajouté un petit endian-swapper, en supposant que la macro BIG_ENDIAN n'est définie que sur une archi big-endian (mips, power-pc...)


Message édité par jesus_christ le 23-10-2005 à 21:46:28
Reply

Marsh Posté le 23-10-2005 à 23:54:22    

Pas static_cast<> mais reinterpret_cast<>.

Reply

Marsh Posté le 24-10-2005 à 14:17:21    

Ok, Merci ça marche très bien !!!   :)  
 
mais j'avoue ne pas bien comprendre le code:
 
   si je comprend bien swapEndian() transforme ce que l'on lui envoi en chaine de caractères et ensuite il échange les éléments opposés (le 1er avec de 4e et le 2e avec le 3e). Et finalement decompose copie la chaine de caractère dans rep. En fait ce que je me demande c'est pourquoi on a fait les échanges de position ???

Reply

Marsh Posté le 24-10-2005 à 19:26:48    

swapEndian transforme par exemple un mot de 32-bits

AB 07 DE F4


en

F4 DE 07 AB


cet ordre s'appelle l' "endian", il y a big endian (bits de poids fort en premier) et little endian (bits de poids faible en premier).
Ici par convention sur le réseau on fait passer du little-endian. Donc sur une machine big-endian, avant l'envoi et après la réception on inverse l'ordre des octets.
Ici j'utilise char comme "octet" et pas comme "caractère" (oui Taz je sais CHAR_BITS ne vaut pas toujours 8, mais bon...)
"p" n'est pas une chaine, c'est un pointeur pour acceder aux vers les différents octets de "data".
 
++fab : t'as raison mais je ne crois pas qu'il existe ou existera un compilo avec lequel ça fera une différence.

Reply

Marsh Posté le 25-10-2005 à 00:23:43    

jesus_christ a écrit :

++fab : t'as raison mais je ne crois pas qu'il existe ou existera un compilo avec lequel ça fera une différence.


le static_cast<> comme tu l'as utilisé étant non conforme, il faut s'attendre à ce qu'un compilo le refuse un jour ...  
D'ailleurs, ce jour est arrivé. gcc4, et icc9 me le refuse logiquement. Par contre, je viens de constater que gcc3.4.4 l'accepte :o

Reply

Marsh Posté le 25-10-2005 à 11:13:58    

ok je m'incline :jap:

Reply

Marsh Posté le 25-10-2005 à 13:18:59    

Ok merci jesus_christ pour ces explication !!! :)

Reply

Marsh Posté le 26-10-2005 à 11:29:46    

vc++7.1 me refuse le static_cast aussi.


---------------
-( BlackGoddess )-
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed