开发者

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_re开发者_StackOverflow中文版c;
      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


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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜