【问题标题】:Can we use any value in floating point for customized flags?我们可以将浮点中的任何值用于自定义标志吗?
【发布时间】:2017-12-23 19:17:28
【问题描述】:

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

我有一个浮点值数组,我想将一些值“标记”为“无效”。一种可能的解决方案是使用另一个位数组来判断相应的值是否有效。

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

  • 根据我的定义,我只需要有效负载中的一位来指示双精度值是否“有效”。输入的双精度值可以包含 NaN,但我认为它不会使用任何有效负载。
  • 双精度值将以二进制模式保存到文件中(逐位保存双精度值)。
  • 那么代码也会以二进制模式从文件中读取数据
  • 对于从文件中读取的每个双精度值,我们首先通过有效负载中设置的位检查它是否有效,然后再进行任何其他计算。

【问题讨论】:

  • 请注意,并非每个支持 NaN 的平台都必须支持 NaN“有效负载”。 IEEE-754 允许使用单个规范 NaN。在实践中,大多数平台都支持 NaN 负载,您通常可以通过 C 和 C++ 的标准库函数 nan() 以实现定义的方式设置它们。
  • C++ 中的 nan 适用于 C++11。我们只有 std::numeric_limits::quiet_NaN() 用于旧 C++。而且它不支持设置有效载荷。通过位掩码设置是否安全...?
  • 是的,您可以使用位操作来访问 NaN 编码,前提是考虑到有关类型重新解释的正常警告。我认为 C++11 是人们此时使用的。我认为,如果您能澄清您计划使用的编程语言和操作系统平台、您需要多少种不同的编码以及您计划如何使用这些编码(例如,是否需要不只是设置,但还要检查程序内部使用的特定编码?我认为没有C/C++标准函数。
  • @njuffa 我更新了我原来的问题来解决你的问题。
  • 在问题中提及目标平台会有所帮助,因为一些软件环境已经为自己的目的预先定义了一些可用的 NaN 编码。我在answer 中针对相关问题给出的具体示例是各种 Apple 平台。

标签: floating-point nan ieee-754


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 对于单精度浮点数(C 中的浮点类型),使用那些高位是否仍然安全?
  • @JoeC 显然,单精度尾数的高位在不同的位置。我会将其添加到答案中以避免歧义。
  • 如果 double 中的 bit[n+29] 映射到 float 中的 bit[n],是否意味着 stackoverflow.com/questions/40785756/… 的位使用仅适用于 double?它使用第 8-15 位,考虑到上述映射,这些位将不存在于浮点数中。或者苹果系统不允许转换之类的?
  • @JoeC 我不知道 Apple SANE 系统如何处理浮点转换。它可能与底层硬件所做的事情相关,或者它可能已经在软件中处理。正如我在答案中所说,我关于有效载荷位映射的发现是经验性的,仅适用于 x64 处理器。对于其他处理器架构,数据类型之间的 NaN 传播行为可能完全不同。
  • @JoeC 如果您需要了解一般浮点格式转换的详细信息,我建议您提出一个新问题。请注意,您的示例中的数字是 not NaN,特别是 8.81620763e-39f 是一个非正规(或次正规)数字(零偏指数),在转换为双精度后变为正常。我关于 floatdouble 之间位图的 cmets 被明确限制为 NaN 有效负载。
猜你喜欢
  • 1970-01-01
  • 2019-02-25
  • 2011-02-20
  • 1970-01-01
  • 2012-05-20
  • 2014-04-09
  • 2018-01-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多