C++ 在不同的平台/架构上浮动和双打

Posted

技术标签:

【中文标题】C++ 在不同的平台/架构上浮动和双打【英文标题】:C++ floats and doubles on different platforms/architectures 【发布时间】:2021-09-11 23:35:38 【问题描述】:

对于上下文,我正在为 Arduino 开发一个库,以通过 LoRa 接收器传输数据包。

我遇到的问题是,库将浮点数和双精度数的原始位放入 uint8_t 数组中,发送它们,然后将它们传输回浮点数和双精度数。

这当然在编译器、平台和架构相同的情况下有效,但在解压它们并将数据直接复制到其他平台(如 Windows 或 Linux 上的 C++)上的浮点数时我会遇到问题吗?

我当然可以使用整数并有一些因素来保留小数位,但这增加了我宁愿以某种方式解决的复杂性。

【问题讨论】:

字节序是您需要担心的事情,所有具有硬件 FPU 的现代系统都使用 IEEE 754 binary32 浮点数和 binary64 双精度数。 en.wikipedia.org/wiki/Double-precision_floating-point_format 当有疑问时,格式化文本是最好的均衡器。这听起来既慢又愚蠢,但它确实有效,而且通常足够快。 让发送方将传出的浮点数从其本机格式转换为标准化格式,然后将该标准格式放入您的字节数组中。让接收器将接收到的标准格式字节中的传入浮点数转换为其本机格式。如果原生格式和传输格式恰好相同,那就这样吧,但不要依赖它,除非作为实现优化。整数、文本、任何多字节数据类型也是如此。不要以原始格式发送数据,将它们标准化。 如果您决定使用格式化文本,请考虑使用"%a" printf 格式。它生成十六进制输出并且不会丢失任何精度(假设浮点基数是 2 的幂,这几乎是肯定的)。 您可以简单地拥有一个由浮点的小数部分和浮点值的小数部分组成的两个整数值的结构,然后发送它而不是原始浮点值。这当然假设您的浮点值在整数范围内。然后发件人确切地知道他们得到了什么,并会相应地处理它。 【参考方案1】:

如果您的实现使用 ieee754 浮点数,并且还具有无符号 32 位和 64 位整数,那么很可能在浮点数和 32 位整数之间以及双精度和 64 位整数之间存在一一对应关系。这恰好适用于我在过去十年中使用的 100% 的实现。 (长双精度更高)。

因此,您可以将浮点数移动到 32 位无符号整数中,通过以任何固定顺序将 x>>24、x>>16、x>>8 和 x 作为字节存储,以某种固定顺序存储四个字节,并且以相同的顺序读回它们。 64 位双精度也是一样。

或者,您可以像 JSON 一样将数字存储为文本。

【讨论】:

【参考方案2】:

如果您只是 memcpy 浮动和加倍,那么无论编译器如何,您都可以在同一平台上使用。

一旦您尝试 memcpy 结构或类,您将需要相同的编译器版本和设置。这是一个巨大的蠕虫罐头。只需检查此站点上有关填充的问题数量即可。它会回来咬你。

出于所有实际目的,现在咬紧牙关,转换为整数或使用序列化工具包(json、protobuf 等)。如果您担心性能,一旦您将序列化为整数或文本工作,添加一个可选的 memcpy 模式,握手通过交换消息来验证兼容性,然后选择任一方法。

【讨论】:

您需要相同的编译器版本和设置。 -- 字节对齐的 POD 结构可以安全发送。

以上是关于C++ 在不同的平台/架构上浮动和双打的主要内容,如果未能解决你的问题,请参考以下文章

浮动索引上的 Berkeley DB C++ 查询

(浮动)NAN 是不是有普遍接受的值 [关闭]

编组 LPSTR 和浮动时的不平衡堆栈

C++ 字符串精确浮动

C/C++编程笔记:C++中的函数重载和浮动

CSS float浮动的深入研究详解及拓展