我们可以为自定义标志使用任何浮点值吗?

Can we use any value in floating point for customized flags?

我在 LINUX RHEL 64 位中编写代码,并使用 C++98。

我有一个浮点值数组,我想 'mark' 一些值是 'invalid'。一种可能的解决方案是使用另一个位数组来判断相应的值是否有效。

我想知道我们是否可以使用任何特殊的双精度值。 link Why does IEEE 754 reserve so many NaN values? 表示有很多 NaN 值。我们可以使用为我的问题保留的任何值吗?

一般来说,IEEE-754 允许但不要求支持 NaN 有效负载。但是,这里我们有 x64 系统的具体情况,AMD 和 Intel 的相关处理器支持 NaN 有效负载。

IEEE Std 754-2008 进一步规定,对于 NaN 编码,尾数的最高有效分数位可区分安静 NaN 和信号 NaN。这对应于单精度和双精度类型的最高有效 stored 尾数位。因此不能将此位用于自定义编码目的。 x64 处理器生成特定的 QNaN INDEFINITE 以响应各种异常情况,并且 QNaN 编码的符号位用于此,因此符号位也禁止用于基于 NaN 的自定义标记。

各种工具链提供宽松的、不符合 IEEE-754 标准的 "fast math",其中不保证 NaN 的传播。您需要使用最严格的浮点设置(例如 Intel 编译器 -fp-model strict)进行编译,以确保自定义标记不会丢失。各种软件环境使用 NaN 有效负载来编码导致创建 NaN 的特定事件(Apple 的 SANE 是此类系统的历史示例)。根据我的经验,此类系统通常使用 NaN 编码的尾数部分的低位。

这表明高阶尾数位,例如 IEEE-754 双精度数的位 50:48 或 IEEE-754 单精度数的位 21:19 是将自定义标志放在 NaN 编码中的最佳位置(如前所述,保留最重要的尾数位不变)。通过 floatdouble 类型传输数据可能会出现问题,因为 x64 架构规范未指定不同浮点类型之间的 NaN 有效负载传播,我可以从审查 AMD 的原始 x64 架构中找到最好的规范和英特尔最新文档。纯粹凭经验,我发现处理 NaN 有效载荷时,单精度编码的位 [n] 显示为双精度编码的位 [n+29],反之亦然。

鉴于编程语言的限制,最好使用memcpy()在浮点和无符号整数表示之间转换,并执行所需的位级操作来设置、清除、测试自定义 NaN整数 space 中的有效载荷。许多优化编译器会优化 memcpy() 并用在 x84 浮点和整数寄存器之间传输数据的硬件指令替换它,但是您需要仔细检查生成的机器代码以确保性能这些操作很重要。