如何在源代码中精确表达浮点常量

Cer*_*rno 1 c++ c++11 floating-point-conversion

我有一些通过代码生成器生成的 C++11 代码,其中包含大量浮点数,并且我想确保编译值与生成器中的编译值完全相同(假设两者都依赖于相同的值)浮动 ISO 标准)

因此,我认为最好的方法是将值存储为十六进制表示形式,并将它们解释为代码中的浮点数。

编辑以澄清: 代码生成器获取浮点值并将它们转换为相应的十六进制表示形式。目标代码应该转换回浮点数。

它看起来像这样:

const unsigned int data[3] = { 0x3d13f407U, 0x3ea27884U, 0xbe072dddU};
float const* ptr = reinterpret_cast<float const*>(&data[0]);
Run Code Online (Sandbox Code Playgroud)

这有效并允许我以浮点形式访问所有数据元素,但我最近偶然发现这实际上是未定义的行为,并且仅有效,因为我的编译器按照我的预期方式解析了它:

https://gist.github.com/shafik/848ae25ee209f698763cffee272a58f8

https://en.cppreference.com/w/cpp/language/reinterpret_cast

该标准基本上表示reinterpret_cast不同类型的 POD 指针之间没有定义。

所以基本上我有三个选择:

  1. 使用memcopy并希望编译器能够对此进行优化

  2. 不将数据存储为十六进制值,而是以不同的方式存储。

  3. std::bit_cast从 C++20开始使用。

我无法使用 3),因为我坚持使用 C++11。

我没有资源来存储数据数组两次,所以我必须依靠编译器来优化它。因此,我不太喜欢 1),因为如果我更改编译器或编译器设置,它可能会停止工作。

所以我只剩下2):

是否有一种标准化的方法来在源代码中表达浮点值,以便它们在编译时映射到精确的浮点值?ISO 浮点标准是否以保证任何编译器都会遵循解释的方式定义了这一点?我想如果我偏离编译器期望的方式,我可能会冒使用我实际想要的数字的浮点“邻居”的风险。

如果有我忘记的选项 4,我也会采取其他想法。

Kam*_*Cuk 5

如何在源代码中精确表达浮点常量

使用十六进制浮点文字。假设您提供的十六进制有一些字节序:

float floats[] = { 0x1.27e80ep-5, 0x1.44f108p-2, -0x1.0e5bbap-3 };
Run Code Online (Sandbox Code Playgroud)

  • 问题是,十六进制浮点文字是在 C++17 中引入的,并且 OP 声明“卡在 C++11 中”。 (4认同)