简体   繁体   中英

How to convert floating-point to unsigned variable?

Could someone please help me with byte ordering regarding floating point variables? Actually the code is working correctly on Solaris, but not on Windows Xp. Here is a piece example of my code: ....

 int x_snd=1;
 float y_snd=1.13;
 struct {
      int xx_snd;
      float yy_snd;
    } data_snd;
 int x_rec;
 float y_rec;
    struct {
      int xx_rec;
      float yy_rec;
    } data_rec;  

 //marshalling 
 data_snd.xx_snd=htons(x_snd);
 data_snd.yy_snd=htonl(*(int*) &y_snd);

 //write data to socket
 send(sock1, &data_snd, ...

 //clean ...

 //read data from socket
 if recv(sock, &data_rec ...

  //unmarshalling
  x_rec=ntohs(data_rec.xx_rec);
  y_rec= *(float*) &(ntohl(data_rec.yy_rec));

...

Th code was compiled with gcc on Unix and with MSVC++6 on wndows. Any of your help would be very appreciated and I would be glad if you could direct me to any link or document that gives usefull information about endianness ...

Thanking you in advance for your help, mk

This is a generally bad idea. The format of floating point numbers isn't necessarily the same on different hardware, even after accounting for byte order. I would have to recommend shipping them here and there as strings.

There's a lot more potential variety and issues in floating point formats than just the endian problem you have to deal with when marshalling and unmarshalling integers.

One way out is to format floating point numbers as text, using printf , and reading them back with strtof() (as bmargulies indicated).

Another way that will work as long as the machines share the same FLT_RADIX value, is to break them into a mantissa and exponent value:

#include <math.h>
#include <limits.h>

float x = 1.13;
int x_exp;
long x_mant;

x_exp = ilogbf(x);
x_mant = (scalbnf(fabsf(x), -x_exp) - 1) * LONG_MAX;
if (x < 0.0)
    x_mant = -x_mant;

You then have an int and a long ( x_exp and x_mant from the above code) to put onto the wire, which you can use the normal ntohl() and htonl() functions to do. To convert these back into a float , use:

x = scalbnf((fabsf(x_mant) / LONG_MAX) + 1, x_exp);
if (x_mant < 0)
    x = -x;

Note that most machines have a FLT_RADIX value (defined in float.h ) of 2, so if you check for that during compilation and abort if it's something else, you should be reasonably portable.

Assuming both systems have the same floating point format, yy_rec is a float ; ntohl takes an unsigned long ; the floating point value, potentially with incorrect endianness, is being converted to an integer representation when it is passed into ntohl .

You should be getting a compiler warning due to the conversion from float to unsigned long .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM