3

尽管大端计算机的使用并不广泛,但我想以独立格式存储双精度数据类型。

对于 int,这真的很简单,因为位移使这非常方便。

int number;
int size=sizeof(number);
char bytes[size];

for (int i=0; i<size; ++i)
    bytes[size-1-i] = (number >> 8*i) & 0xFF;

此代码片段以大端格式存储数字,尽管它正在运行的机器上。双倍最优雅的方法是什么?

4

6 回答 6

7

可移植性和考虑格式的最佳方法是分别序列化/反序列化尾数和指数。为此,您可以使用 frexp()/ldexp() 函数。

例如,要序列化:

int exp;
unsigned long long mant;

mant = (unsigned long long)(ULLONG_MAX * frexp(number, &exp));

// then serialize exp and mant.

然后反序列化:

// deserialize to exp and mant.

double result = ldexp ((double)mant / ULLONG_MAX, exp);
于 2012-11-07T21:32:07.153 回答
5

优雅的做法是将字节顺序问题限制在尽可能小的范围内。那个狭窄的范围就是你的程序和外部世界之间的 I/O 边界。例如,将二进制数据发送到其他应用程序/从其他应用程序接收二进制数据的函数需要注意字节序问题,将二进制数据写入/从某个数据文件读取二进制数据的函数也是如此。让这些接口认识到表示问题。

让其他一切都幸福地忽略这个问题。在其他地方使用本地表示。将双精度浮点数表示为 adouble而不是 8 字节数组,将 32 位整数表示为 anintint32_t而不是 4 字节数组,等等。在整个代码中处理字节顺序问题会使您的代码臃肿、容易出错和难看。

于 2012-11-07T21:39:47.557 回答
1

相同。任何数字对象,包括双精度对象,最终都是几个字节,这些字节根据字节顺序以特定顺序进行解释。因此,如果您恢复字节顺序,您将在反转字节序中获得完全相同的值。

于 2012-11-07T21:19:09.187 回答
1
 char *src_data;
 char *dst_data;

 for (i=0;i<N*sizeof(double);i++) *dst_data++=src_data[i ^ mask];
 // where mask = 7, if native == low endian
 // mask = 0, if native = big_endian

优雅之处在于mask它还处理短类型和整数类型:如果目标和源字节序不同,它的 sizeof(elem)-1 。

于 2012-11-07T21:19:47.097 回答
0

不是很便携且违反标准,但是像这样:

std::array<unsigned char, 8> serialize_double( double const* d )
{
  std::array<unsigned char, 8> retval;
  char const* begin = reinterpret_cast<char const*>(d);
  char const* end = begin + sizeof(double);
  union 
  {
    uint8  i8s[8];
    uint16 i16s[4];
    uint32 i32s[2];
    uint64 i64s;
  } u;
  u.i64s = 0x0001020304050607ull; // one byte order
 //  u.i64s = 0x0706050403020100ull; // the other byte order

  for (size_t index = 0; index < 8; ++index)
  {
    retval[ u.i8s[index] ] = begin[index];
  }
  return retval;
}

可以处理具有 8 位字符、8 字节双精度和任何疯狂的字节顺序的平台(例如,对于 64 位值,字中的大端序,但字之间的小端序)。

现在,这并没有涵盖与 64 位整数不同的双精度字节序。

一种更简单的方法可能是将您的 double 转换为 64 位无符号值,然后像其他任何 int 一样输出。

于 2012-11-07T22:01:21.350 回答
0
void reverse_endian(double number, char (&bytes)[sizeof(double)])
{
    const int size=sizeof(number);
    memcpy(bytes, &number, size);
    for (int i=0; i<size/2; ++i)
        std::swap(bytes[i], bytes[size-i-1]);
}
于 2012-11-08T16:32:09.477 回答