Как преобразовать число с плавающей точкой в ​​беззнаковую переменную? - PullRequest
0 голосов
/ 12 ноября 2009

Может кто-нибудь помочь мне с порядком байтов для переменных с плавающей запятой? На самом деле код работает правильно на 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));

...

Th-й код был скомпилирован с помощью gcc в Unix и с MSVC ++ 6 для wndows. Буду очень признателен за любую вашу помощь, и я был бы рад, если бы вы могли направить меня на любую ссылку или документ, который дает полезную информацию о порядке байтов ...

Заранее благодарю за помощь, тк

Ответы [ 3 ]

2 голосов
/ 12 ноября 2009

В форматах с плавающей запятой существует гораздо больше потенциальных вариаций и проблем, чем просто проблема с порядком байтов, с которой вам приходится сталкиваться при маршалинге и демаршаллинге целых чисел.

Одним из выходов является форматирование чисел с плавающей запятой в виде текста с использованием 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_exp и x_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, поэтому, если вы проверите это во время компиляции и прервете, если это что-то еще, вы должны быть достаточно переносимы.

2 голосов
/ 12 ноября 2009

Это вообще плохая идея. Формат чисел с плавающей запятой не обязательно одинаков на разных аппаратных средствах, даже после учета порядка байтов. Я бы рекомендовал отправлять их здесь и там в виде строк.

1 голос
/ 12 ноября 2009

Предполагая, что обе системы имеют одинаковый формат с плавающей запятой, yy_rec представляет собой float; ntohl занимает unsigned long; значение с плавающей запятой, потенциально с неправильным порядком байтов, преобразуется в целочисленное представление, когда оно передается в ntohl.

Вы должны получить предупреждение компилятора из-за преобразования из float в unsigned long.

...