如何检查C++编译器是否使用IEEE 754浮点标准

35

我想问一个跟这个问题相关的问题,该问题已通过检查编译器使用标准来很好地回答了。但是这仅适用于C语言。在C++中是否有相同的方法?

我不想将浮点类型转换为文本或使用某些相当复杂的转换函数,我只需要进行编译器检查。如果您知道这样的兼容编译器列表,请发布链接。我找不到它。


7
在运行时,您可以使用std::numeric_limits<double>::is_iec559()来检查特定浮点类型是否按照IEEE 754标准表示。当然,这并不能说明编译器的浮点数处理是否符合754标准,但这应该会给您一个很好的提示。 - Alexander Gessler
我认为这不完全是编译器支持的问题,更多的是CPU的FPU是否支持它...但我不是100%自信,所以我只能做出评论而不是回答。 - Max E.
2
@AlexanderGessler 在运行时?你确定吗?http://en.cppreference.com/w/cpp/types/numeric_limits/is_iec559 - cubuspl42
1
@cubuspl42:现在是constexpr,但你正在回复一个早于C++11的评论。 - Ben Voigt
2个回答

40
实际上,在C++中,你有一种更简单的方法来实现这个。根据C++标准18.2.1.1,类numeric_limits存在于std命名空间中。为了访问该静态成员,你只需这样做:
std::numeric_limits<double>::is_iec559;

或者:

std::numeric_limits<float>::is_iec559;

如果使用IEEE 754,应该返回true;否则返回false。
作为另一种方法,Adam's answer的第二部分也可以用于C++。

3
实际上这并不完全可靠。你可以称之为“不符合规范”,但编译器不一定知道它们的浮点类型是否符合IEEE754标准,因为它们生成的机器代码在多种架构的变体上运行,其中有些在ulp精度和使用正确舍入模式的每个细节上都符合规范,而有些则不符合。 - Steve Jessop
1
@Steve 说得很对。不幸的是,我不知道有任何其他合理标准/理智的测试方法来测试这个问题,除非找出你所在的架构并基于是否已知正在执行的芯片系列完全符合来添加检查。 - user257111
1
我认为这对于我们的目的来说是可以的,所有提问者似乎真正关心的只是格式,而不是符合IEC559的整体要求。你可能会从编译器那里得到一个错误的负面回答,它保守地表示它没有实现IEC559,但它已经足够满足我们的需求了。只是值得注意的是,这对编译器来说实际上是一件困难的事情,所以要警惕奇怪的问题。 - Steve Jessop
@SteveJessop,你能更具体一些吗?你是在谈论像x86或ARM这样的流行架构,还是更奇特的东西?我认为,如果你的CPU架构的程序员手册没有严格定义浮点运算,那么is_iec559应该为false。或者,根据某些编译器开关,它应该是软件模拟和true,或者IEEE 754不兼容和false。对我来说,这似乎不是一个概念上的问题,但也许我漏掉了什么。 - cubuspl42
1
@cubuspl42:我说的是当 is_iec559false 的情况,因为该类型仅与 IEEE 754 兼容度达到了 99.99%。我不记得当时为什么会这样想,但根据我上面的评论,我认为问题的真正需要知道的是是否使用了 IEEE 格式,而不是是否严格遵循了 IEEE 语义。因此会有假阴性,但由于问题的真正需求没有正式定义,所以无法避免。 - Steve Jessop
哦,我认为我之所以这样想是因为这个OP提到的链接问题只谈论了格式,而没有谈论每个操作的最后一位ulp是否正确。无论如何,我认为我也看到过石头冷漠的漏洞,其中实现者(通常是平台维护者)未能让is_iec559错误地为某些几乎但不完全符合IEEE 754标准的目标。这些天,流行的架构可能确实是正确的,这在保持流行的要求下也是必要的;-) - Steve Jessop

0

虽然这篇文章有点老(10年),但你仍然可以尝试。它也适用于C语言:

#ifndef __STDC_IEC_559__
#error The following Programm only supports float operations using the IEEE 754 Standard
#endif

你有这方面的任何来源吗?__STD_IEC_559__是由编译器自身定义的吗?在 C99 中,它在 math.h 中定义,因此您必须先 #include <math.h> 然后测试该定义。在 C++ 中它在哪里定义? - wovano
它也在 stdc-predef.h 中定义,该头文件从 stdint.h 中获取,后者也用于 C++ (甚至是从 iostream 中)。我想,我假定用户已经包含了其中一个库。 - AKJ
1
这个答案中有一些解释:https://dev59.com/_nRB5IYBdhLWcg3wAjJH#753018 - Dominik Mokriš

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接