当应用于浮点值时,std::abs和std::fabs之间有什么区别吗

Is there any difference between std::abs and std::fabs when applied to floating point values?

本文关键字:std 之间 fabs 什么 区别 应用于 abs      更新时间:2023-10-16

有一个相关的问题,但我相信它不能回答这个问题。

std::absstd::fabs文档来看,它们似乎具有完全相同的行为。作为个人注意事项,在我看来,std::fabs是优选的,因为它缓解了<cstdlib>std::abs(int)定义的模糊性(参见注意事项)。

所以我的问题是:除了std::abs(int)潜在的模糊性之外,当应用于浮点值时,std::absstd::fabs之间有什么区别吗?

在包含cmath并且仅在floats、doubles和long doubles上调用std::abs的标准一致性代码中,没有差异。然而,当您在包含各种头文件集的情况下调用std::abs时,查看CCD_14在各种类型上返回的类型是很有指导意义的。

在我的系统中,如果我包含cmath而不包含cstdlib,则std::abs(-42)double;如果我包含了cstdlib,则int;如果两者都不包含,则会产生编译错误。相反,如果我包含了cstdlib但没有包含cmath,则std::abs(-42.0)会产生编译错误(不明确的重载);如果两者都没有包含,则会产生不同的编译错误(从未听说过std::abs)。

在我的平台上,如果我包含了cmathstd::abs('x')会给我一个double;如果我包含cstdlib但不包含cmath,则会给我int。类似于short int。意义似乎并不重要。

在我的平台上,complex标头显然会同时声明std::abs的整数和浮点重载。我不确定这是强制性的;也许您可以找到一个合理的平台,在该平台上std::abs(1e222)返回无穷大,并包含一组错误的标准标头。


"您忘记了程序中的头"的常见后果是编译失败,抱怨未定义的符号,而不是行为的无声变化。然而,对于std::abs,如果您忘记了cstdlib,则结果可能是std::abs(42)返回double;如果您没有忘记,则结果是std::abs('x')返回int。(或者,当你传递short时,你可能希望std::abs给你一个积分类型?然后,假设我的编译器正确地获得了升级和重载解决方案,你最好确保不包括cmath。)

在过去,我也花了太多时间试图弄清楚为什么像double precise_sine = std::sin(myfloat)这样的代码会给出不精确的结果。因为我不喜欢把时间浪费在这些意外上,所以我倾向于避免namespace std中标准C函数的重载变体。也就是说,当我希望返回double时,我使用::fabs,当我想要输出float时使用::fabsf,当我需要输出long double时使用::fabsl。类似地,当我想要int::abs,当我需要long::absl,以及当我想要CCD 57时::absll

当应用于浮点值时,std::abs和std::fabs之间有什么区别吗?

不,没有。积分类型也没有区别。

使用std::abs()是习惯用法,因为它最接近常用的数学命名法。