【问题标题】:Detect IEEE-754 floating point representation at compile time在编译时检测 IEEE-754 浮点表示
【发布时间】:2020-11-19 07:11:37
【问题描述】:

我正在寻找一种方法来检测 C 编译器是否在编译时使用 IEEE-754 浮点表示,最好是在预处理器中,但常量表达式也可以。

请注意,__STDC_IEC_559__ 宏不适合此目的,因为实现可能使用正确的表示,但不完全支持附件 F。

【问题讨论】:

  • 编译器本身很可能会“使用”底层硬件使用的任何格式。
  • @Someprogrammerdude 我认为他的意思是“实现”,是硬件、编译器、库等的组合。
  • __STDC_IEC_559__ 的一个常见问题是它“应实现浮点类型(OP 想要的 - 很容易遵守)和符合 IEC 60559 的算术(困难部分)”。 “符合 IEC 60559 的算术”是一项艰巨的测试,更不用说通过了。一些高度兼容的编译器将其保留为未定义,而不是冒险错过极端情况。

标签: c ieee-754 compile-time


【解决方案1】:

不是一个绝对 100% 的解决方案,但会让你几乎接近。

检查浮动类型double的特征是否匹配binary64

#include <float.h>

#define BINARY64_LIKE ( \
  (FLT_RADIX == 2) \
  (DBL_MANT_DIG == 53)  \
  (DBL_DECIMAL_DIG == 17) \
  (DBL_DIG == 15) \
  (DBL_MIN_EXP == -1021) \
  (DBL_HAS_SUBNORM == 1) \
  (DBL_MIN_10_EXP == -307) \
  (DBL_MAX_EXP == +1024) \
  (DBL_MAX_10_EXP == +308))

BINARY64_LIKE 在编译时可用。但是对于没有定义它们的旧编译器需要额外的工作,例如:DBL_HAS_SUBNORM 自 C11 以来。

float 也是如此。

从 C11 开始,代码可以使用_Static_assert() 来检测一些属性。

_Static_assert(sizeof(double)*CHAR_BIT == 64, "double unexpected size");

另见Are there any commonly used floating point formats besides IEEE754?

我上次使用的非 IEEE754 FP 格式是 5 年前的CCSI


警告:不清楚为什么 OP 想要这个测试。如果代码正在对浮点进行一些位操作,即使定义了__STDC_IEC_559__,仍然至少存在一个漏洞:浮点和整数的字节序可能不同 - 不常见 - 但在那里。

其他潜在漏洞:支持 -0.0、NaN 符号、无穷大编码、信号 NaN、安静 NaN、NaN 有效负载:通常的嫌疑人。

【讨论】:

  • @Myst 感谢您的链接。除了 DBL_MAX, FLT_MIN 之类的特征之外,几乎可以使用所有特征,因为这些特征不能与预处理器数学一致地工作。
  • 没有必要检查名称中带有DECIMAL10的值,因为它们是其他函数,除了无穷大和NaN支持之外,它们完全表征了可表示的值。 (假设,一种格式可以使用更多位并允许非规范化表示。但如果可表示的值的集合是相同的。)
  • @EricPostpischil 合理的简化。
  • “浮点和整数的字节序可能不同” - 我不知道这个问题,谢谢你提到它。有什么直接的方法可以检测到这一点吗?
【解决方案2】:

截至 2020 年 7 月,这仍将是特定于编译器的...尽管 C2x intends to change that with the __STDC_IEC_60559_BFP__ macro - 请参阅附件 F,第 F.2 节。

需要注意的是:

  • 编译器通常不选择二进制表示。编译器通常遵循目标系统的架构(CPU/GPU 的芯片组指令设计等)。

  • 对浮点数使用不合格的二进制表示几乎已成为过去。如果您使用的是过去 10 年的现代(甚至是中等现代)系统,那么您几乎肯定在使用符合要求的二进制表示。

【讨论】:

  • @KamilCuk,是的,你是对的。我通常用粗略的笔触绘画,而错过了那幅画的细节。我更新了答案,希望现在更好。
  • 在我看来,__STDC_IEC_60559_BFP__ 仍然需要一致性算术。我是否误读了标准草案?
  • @vktec 宏还要求floatdouble 类型使用特定的IEEE 754 二进制表示(尽管使用更新的规范文档和名称)。这是你问题的根源,对吧?
  • 那么它和__STDC_IEC_559__有同样的问题:在内存中使用所需的representation的实现可能无法正确实现所有操作,因此可能无法定义宏跨度>
猜你喜欢
  • 2012-01-06
  • 1970-01-01
  • 2014-10-18
  • 1970-01-01
  • 2017-04-08
  • 1970-01-01
  • 2013-07-24
  • 2016-11-06
  • 1970-01-01
相关资源
最近更新 更多