我们可以为自定义标志使用任何浮点值吗?
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 值。我们可以使用为我的问题保留的任何值吗?
- 根据我的定义,我只需要有效载荷中的一位来指示双精度值是否为 'valid'。输入的双精度值可以包含 NaN,但我假设它不会使用任何负载。
- 双精度值将以二进制方式保存到文件中(逐位保存双精度值)。
- 然后代码也以二进制方式从文件中读取数据
- 对于从文件中读取的每个 double 值,在进行任何其他计算之前,我们首先通过 payload 中设置的位检查它是否有效。
一般来说,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 编码中的最佳位置(如前所述,保留最重要的尾数位不变)。通过 float
和 double
类型传输数据可能会出现问题,因为 x64 架构规范未指定不同浮点类型之间的 NaN 有效负载传播,我可以从审查 AMD 的原始 x64 架构中找到最好的规范和英特尔最新文档。纯粹凭经验,我发现处理 NaN 有效载荷时,单精度编码的位 [n] 显示为双精度编码的位 [n+29],反之亦然。
鉴于编程语言的限制,最好使用memcpy()
在浮点和无符号整数表示之间转换,并执行所需的位级操作来设置、清除、测试自定义 NaN整数 space 中的有效载荷。许多优化编译器会优化 memcpy()
并用在 x84 浮点和整数寄存器之间传输数据的硬件指令替换它,但是您需要仔细检查生成的机器代码以确保性能这些操作很重要。
我在 LINUX RHEL 64 位中编写代码,并使用 C++98。
我有一个浮点值数组,我想 'mark' 一些值是 'invalid'。一种可能的解决方案是使用另一个位数组来判断相应的值是否有效。
我想知道我们是否可以使用任何特殊的双精度值。 link Why does IEEE 754 reserve so many NaN values? 表示有很多 NaN 值。我们可以使用为我的问题保留的任何值吗?
- 根据我的定义,我只需要有效载荷中的一位来指示双精度值是否为 'valid'。输入的双精度值可以包含 NaN,但我假设它不会使用任何负载。
- 双精度值将以二进制方式保存到文件中(逐位保存双精度值)。
- 然后代码也以二进制方式从文件中读取数据
- 对于从文件中读取的每个 double 值,在进行任何其他计算之前,我们首先通过 payload 中设置的位检查它是否有效。
一般来说,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 编码中的最佳位置(如前所述,保留最重要的尾数位不变)。通过 float
和 double
类型传输数据可能会出现问题,因为 x64 架构规范未指定不同浮点类型之间的 NaN 有效负载传播,我可以从审查 AMD 的原始 x64 架构中找到最好的规范和英特尔最新文档。纯粹凭经验,我发现处理 NaN 有效载荷时,单精度编码的位 [n] 显示为双精度编码的位 [n+29],反之亦然。
鉴于编程语言的限制,最好使用memcpy()
在浮点和无符号整数表示之间转换,并执行所需的位级操作来设置、清除、测试自定义 NaN整数 space 中的有效载荷。许多优化编译器会优化 memcpy()
并用在 x84 浮点和整数寄存器之间传输数据的硬件指令替换它,但是您需要仔细检查生成的机器代码以确保性能这些操作很重要。