为什么浮点数字节交换与整数字节交换不同?

3
我有一个double类型的二进制文件需要在C++中加载。然而,我的问题是它以大端格式编写,但由于我的机器是小端,fstream>>操作符将读取错误的数字。对于整数,这似乎是一个简单的问题,但对于double和float,我找到的解决方案不起作用。我该如何解决这个问题?
我阅读了这篇文章作为整数字节交换的参考:
How do I convert between big-endian and little-endian values in C++? 编辑:虽然这些答案很有启发性,但我发现我的问题在于文件本身而不是二进制数据的格式。我相信我的字节交换确实起作用了,我只是得到了令人困惑的结果。谢谢你的帮助!

我本来期望双精度/单精度浮点数的字节交换解决方案能够完全相同(也就是说,定义一个float/int32联合体,在其中写入错误字节序的float,对int32进行字节交换,然后再次读取float),因此我认为您必须解释一下哪些解决方案不起作用。 - Pascal Cuoq
2个回答

6
最便携的方法是将数据序列化为文本格式,这样您就不必担心字节顺序问题。这也是operator>>的工作方式,因此您不应该在使用>>时遇到任何字节序问题。二进制格式的主要问题(可能会导致字节序问题)是浮点数由若干个尾数位、若干个指数位和一个符号位组成。指数可能使用偏移量。这意味着直接进行字节重新排序可能不足够,这取决于源格式和目标格式。
如果两台计算机都使用IEEE-754,则通过简单的字节翻转可能可以解决问题,因为此标准规定了一种比特串交换格式,应该是可移植的(除字节顺序问题外)。
如果您需要在两个机器体系结构之间进行转换,并且必须使用原始字节内存转储,则只要基本数字格式相同(即它们在数字的每个部分具有相同的比特数),您就可以将数据读入unsigned char数组中,使用一些基本的字节和位交换例程来更正存储格式,然后将原始字节复制到适当类型的变量中。

你不必以文本格式进行序列化 - 你可以使用面向值而非面向表示的方法将浮点数转换为三个整数(符号、尾数和指数),然后按照通常的方式将这些整数序列化为网络字节顺序。 - caf
我很好奇:是否有任何不属于IEEE-754的非主流芯片? - Will
@caf:你可以跳过一步,将它们转换为两个值:有符号的尾数和指数。但是在网络字节顺序中进行(反)序列化的标准方式值得回答。 - Potatoswatter
@caf:我正在努力思考一种整数的常见值导向表示方式,它不受大小端问题的影响,也不是文本形式。你是指类似于UTF-8对大型Unicode代码点所做的事情吗? - CB Bailey
对于整数,只需定义字节序(和大小)即可 - 因此称为“网络字节顺序”。对于“面向值”的概念,我指的是提取浮点数组件的过程(例如使用ilogb()函数或等效函数而不是直接屏蔽底层表示的部分)。 - caf

0

标准的转换运算符不能处理二进制数据,所以你到底是怎么得到这个结果的并不清楚。

然而,由于字节交换操作是针对字节而不是数字进行的,因此你可以对将成为浮点数的数据执行与将成为整数的数据相同的操作。

而且,由于文本效率低下,浮点数据集往往非常大,因此想要这样做是完全合理的。

int32_t raw_bytes;
stream >> raw_bytes; // not an int, just 32 bits of bytes
my_byte_swap( raw_bytes ); // swap 'em
float f = * reinterpret_cast< float * >( & raw_bytes ); // read them into FPU

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接