我注意到,当将浮点输入传递给
cmath
的 sqrt
时,appleclang++ (v14.0.0) 似乎返回单精度浮点。当切换到 gcc/clang 时,我很惊讶地得到了不同的结果。
这是我的最小可重现示例:
#include <cmath>
#include <cstdio>
#include <type_traits>
int main()
{
float f = 1+1e-7;
auto X = sqrt(f);
printf("%16s says X is a %6s with value: %0.17g\n",
#ifdef __clang__
#if defined(__apple_build_version__)
"appleclang++",
#else
"clang++",
#endif
#elif __GNUC__
"g++",
#else
"unknown compiler",
#endif
std::is_same<float, decltype(X)>::value ? "float" : "double",
X);
}
对于不同的编译器,我看到:
appleclang++ says X is a float with value: 1
clang++ says X is a double with value: 1.000000059604643
g++ says X is a double with value: 1.000000059604643
我正在使用
-std=c++11
进行编译,只是为了确定。
如果我切换到std::sqrt
,那么每个人都同意这是一个浮动,但我仍然很好奇。
sqrt
的这种行为确实是由编译器决定还是 appleclang 是非标准的?
sqrt
,这是错误的。应该是
std::sqrt
。当包含
<cmath>
时,只能保证
std::sqrt
的所有重载都在
std::
命名空间范围内提供。您需要包含
<math.h>
以保证所有重载在全局命名空间范围内也可用。当包含不匹配时,未指定哪些重载将可见,然后有可能不是获得
float sqrt(float)
重载,而是获得
double sqrt(double)
重载,或任何其他重载,例如期望 和
int
并返回
double
(这会导致非常奇怪的结果)。