浮点表达式有时可以在处理硬件上收缩,例如使用融合的乘法和加法作为单个硬件操作。
显然,使用这些不仅是实现细节,还受编程语言规范的约束。具体而言,C89标准不允许此类收缩,而在C99中,只要定义了某些宏,则允许此类收缩。请参阅this SO answer中的详细信息。
但是C++呢?浮点收缩是不允许的吗?在某些标准中允许?普遍允许吗?
最佳答案
概括
允许收缩,但是为用户提供了禁用收缩的功能。标准中的语言不清晰笼罩了是否禁用它们将提供所需结果的问题。
我在C++ 2003官方标准和2017 n4659草案中对此进行了调查。除非另有说明,否则对C++的引用均来自2003年。
更高的精度和范围
文本“契约(Contract)”没有出现在两个文档中。但是,第5条表达式[expr]第10段(与2017年8 [expr] 13中的相同文字)指出:
我希望此声明明确声明是可以自由使用此额外精度和范围(实现可以在某些表达式中使用它,包括子表达式,而在其他表达式中不使用它)还是必须统一使用(如果实现使用额外精度) ,则必须在每个浮点表达式中使用它)或根据其他规则使用(例如,它可能对float
使用一种精度,对double
使用另一种精度)。
如果我们对它进行宽泛的解释,则意味着在a*b+c
中,a*b
可以以无限的精度和范围进行评估,然后可以以实现时正常的精度和范围来评估加法。从数学上讲,这等效于收缩,因为它的结果与使用融合的乘法加法指令评估a*b+c
的结果相同。
因此,通过这种解释,实现可以收缩表达式。
从C继承的收缩
17.4.1.2 [lib.headers] 3(2017年20.5.1.2 [headers] 3中的类似文字)说:
表12包含<cmath>
,第4段指出这与math.h
相对应。从技术上讲,C++ 2003标准指的是C 1990标准,但是我没有电子形式的文件,也不知道我的纸质拷贝在哪里,因此我将使用C 2011标准(但非官方草案N1570),该标准是C++ 2017年草案指的是。
C标准在<math.h>
中定义了一个编译指示FP_CONTRACT
:
#pragma STDC FP_CONTRACT on-off-switch
其中on-off-switch是
on
以允许表达式收缩,或者off
禁止表达式。它还表示编译指示的默认状态是实现定义的。C++标准未定义“设施”或“设施”。词典对“设施”的定义是“为特定目的而提供的场所,设施或设备”(新牛津美国词典,Apple词典应用程序版本2.2.2(203))。便利设施是“建筑物或地方的理想或有用功能或设施”。编译指示是为特定目的提供的有用功能,因此它似乎是一种功能,因此包含在
<cmath>
中。因此,使用该实用指示应允许或禁止收缩。
结论
FP_CONTRACT
启用时,允许收缩,并且默认情况下可以启用。 FP_CONTRACT
处于关闭状态,但对于明确的解释来说,8 [expr] 13的文本仍可被解释为有效地允许收缩。