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

Posted

技术标签:

【中文标题】应用于浮点值时,std::abs 和 std::fabs 之间有啥区别吗?【英文标题】:Is there any difference between std::abs and std::fabs when applied to floating point values?应用于浮点值时,std::abs 和 std::fabs 之间有什么区别吗? 【发布时间】:2015-12-09 18:00:46 【问题描述】:

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

看看std::abs and std::fabs documentation,他们似乎有完全相同的行为。作为个人说明,在我看来std::fabs 更可取,因为它减轻了<cstdlib>std::abs(int) 定义的歧义(参见note)。

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

【问题讨论】:

还有***.com/questions/33738509/… 不知道你怎么看不到。 std::absstd::fabs 具有相同的行为。 【参考方案1】:

在包含cmath 并且仅在floats、doubles 和long doubles 上调用std::abs 的符合标准的代码中,没有区别。但是,当您调用 std::abs 并包含各种头文件集时,查看 std::abs 在各种类型上返回的类型是有益的。

在我的系统上,std::abs(-42)double,如果我已包含 cmath 但不是 cstdlib,如果我已包含 int,则为 int,如果我包含'没有包括。相反,如果我包含了cstdlib 但我没有包含cmath 或其他编译错误(从未听说过std::abs),则std::abs(-42.0) 会产生编译错误(不明确的重载),如果我没有包含两者。

在我的平台上,如果我包含了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。对于::abs,当我想要int::absl,当我想要long::absll,当我想要long long

【讨论】:

【参考方案2】:

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

不,没有。整数类型也没有区别。

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

【讨论】:

以上是关于应用于浮点值时,std::abs 和 std::fabs 之间有啥区别吗?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 std::abs() 不能与浮点数一起使用

Visual Studio 单元测试:为啥在测试相同的浮点值时测试运行不确定?

(Rcpp)armadillos abs() 函数在 std::abs 工作时与 c++ double 一起使用时输出错误值

浮点错误 gfortran

将强制转换应用于整数和浮点除法的结果:这里发生了啥?

整型与浮点型相互转换的相关问题