【问题标题】:How to convert floating-point to unsigned variable?如何将浮点数转换为无符号变量?
【发布时间】:2009-11-11 23:38:35
【问题描述】:

有人可以帮我处理浮点变量的字节顺序吗?实际上,代码在 Solaris 上可以正常工作,但在 Windows Xp 上却不行。这是我的代码的一个示例: ....

 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));

...

代码在 Unix 上用 gcc 编译,在 wndows 上用 MSVC++6 编译。 您的任何帮助将不胜感激,如果您能指导我访问任何提供有关字节序的有用信息的链接或文档,我将非常高兴...

提前感谢您的帮助, 马克

【问题讨论】:

    标签: c byte endianness


    【解决方案1】:

    除了在编组和解组整数时必须处理的字节序问题之外,浮点格式还有更多潜在的多样性和问题。

    一种方法是使用printf 将浮点数格式化为文本,然后使用strtof() 将它们读回(如bmargulies 所示)。

    只要机器共享相同的FLT_RADIX 值,另一种可行的方法是将它们分解为尾数和指数值:

    #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;
    

    然后你有一个int 和一个long(上面代码中的x_expx_mant)放到电线上,你可以使用普通的ntohl()htonl() 函数来做.要将这些转换回float,请使用:

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

    请注意,大多数机器的 FLT_RADIX 值(在 float.h 中定义)为 2,因此,如果您在编译期间检查该值并在其他情况下中止,那么您应该是相当可移植的。

    【讨论】:

    • 感谢您的帮助,您能否给我更多关于您描述的第二个的信息?任何描述这种 FLT_RADIX 值的链接将不胜感激!再次感谢,MK
    • 好吧,我已经为您提供了代码(我只是自己编写的,所以我没有任何链接可以指向您)。如果您对表示浮点数的 Sign-Mantissa-Exponent 方式进行一些研究,您应该清楚代码在做什么。
    • 感谢您的帮助。请纠正我,如果这是正确的!诠释 x_snd=1;浮动 y_snd=1.13; // int y_snd_exp;长 y_snd_mant;结构 { int xx_snd;浮动 yy_snd; } 数据_snd; //编组 y_snd_exp = ilogbf(y_snd); y_snd_mant = (scalbnf(fabsf(y_snd), -y_​​snd_exp) - 1) * LONG_MAX;如果(y_snd
    • int x_rec;浮动 y_rec; // int y_rec_exp;长 y_rec_mant;结构 { int xx_rec;浮动 yy_rec; } 数据记录; //从套接字读取数据 if recv(sock1, &data_rec ... //解组 x_rec=ntohs(data_rec.xx_rec); y_rec_mant=ntohl(data_rec.yy_rec); x = scalbnf((fabsf(y_rec_mant) / LONG_MAX) + 1 , y_rec_exp); if (y_rec_mant
    • 没有。 y_snd_expy_snd_mant 值都应该通过网络发送(在通过htonl() 之后)。您也不能像这样一次性编写struct - 结构可以有填充。您应该分别编写每个值。
    【解决方案2】:

    这通常是个坏主意。即使在考虑字节顺序之后,浮点数的格式在不同的硬件上也不一定相同。我不得不建议将它们作为字符串到处发送。

    【讨论】:

      【解决方案3】:

      假设两个系统具有相同的浮点格式,yy_recfloatntohl 接受unsigned long;浮点值(可能具有不正确的字节顺序)在传递到ntohl 时被转换为整数表示。

      由于从floatunsigned long 的转换,您应该会收到编译器警告。

      【讨论】:

      • 这很关键。编写的代码( y_rec= (float) &(ntohl(data_rec.yy_rec)); )不应该工作,因为它将 yy_rec (浮点数)转换为无符号长然后翻转它的字节数。
      猜你喜欢
      • 2013-11-01
      • 2011-04-23
      • 1970-01-01
      • 2019-12-09
      • 2010-10-23
      • 2015-12-28
      • 2018-08-07
      • 2010-11-24
      • 1970-01-01
      相关资源
      最近更新 更多