什么是abs和fabs的区别?

43

我在这里查看了Python中absfabs的区别:here

据我所知,它们在速度和传递类型方面存在一些差异,但我的问题与V.S.上的原生C++有关。

关于V.S.,我在Visual Studio 2013 (v120)上尝试了以下内容:

float f1= abs(-9.2); // f = 9.2
float f2= fabs(-9); // Compile error [*]

因此fabs(-9)会给我编译器错误,但当我尝试执行以下操作时:

double i = -9;
float f2= fabs(i); // This will work fine
我理解第一段代码的问题在于,fabs(-9)需要一个double参数,但编译器无法将-9转换为-9.0,因此代码无法编译。而在第二段代码中,编译器会在编译时将i=-9转换为i=-9.0,所以fabs(i)可以正常工作。

还有,为什么编译器不能像C#那样自动接受fabs(-9)并将int值自动转换为double?

[*]:

Error: more than one instance of overloaded function "fabs" matches the argument list:
        function "fabs(double _X)"
        function "fabs(float _X)"
        function "fabs(long double _X)"
        argument types are: (int)   

没有编译器错误:http://coliru.stacked-crooked.com/a/80c5484bda892461 - NathanOliver
3个回答

42
在C++中,std::abs对于有符号整数和浮点类型都进行了重载。而std::fabs仅处理浮点类型(在C++11之前)。请注意,std::很重要;由于历史遗留原因通常可以使用的C函数::abs只能处理int
问题在于
float f2= fabs(-9);

问题并不是没有从 int-9的类型)到 double 的转换,而是编译器不知道该选择哪种转换(int -> floatdouble 或者 long double),因为这三个类型都有一个 std::fabs。你的解决方法明确告诉编译器使用 int -> double 的转换,所以二义性消失了。

C++11 通过添加 double fabs( Integral arg ); 来解决这个问题,它将返回任何整数类型转换为 double 后的绝对值。显然,在 C++98 模式下,libstdc++ 和 libc++ 也可用此重载。

总之,只需使用 std::abs,它会做正确的事情。(由@Shafik Yaghmour指出的有趣的陷阱。在 C++ 中,无符号整数类型会发生奇怪的事情。)


4
一般情况下,只需使用std::abs,它会执行正确的操作。参见Is std::abs(0u) ill-formed? - Shafik Yaghmour
@ShafikYaghmour 有趣,我从未遇到过这种情况。令人惊讶的是,无符号整数在C++中造成了如此多的混乱。将无符号整数转换为double的“正确”实现并不符合我的预期,老实说。 - Baum mit Augen
1
不要误解我的意思,这是一个好答案,我偶然遇到了它,特别是因为有实现差异并且仍然开放,所以意识到这一点很重要。 - Shafik Yaghmour
@ShafikYaghmour 同意,我在答案中添加了一条备注,谢谢。 - Baum mit Augen

17

使用C++11,仅使用abs()是非常危险的:

#include <iostream>
#include <cmath>

int main() {
    std::cout << abs(-2.5) << std::endl;
    return 0;
}

这个程序的输出结果是2。(在线演示

始终使用std::abs()

#include <iostream>
#include <cmath>

int main() {
    std::cout << std::abs(-2.5) << std::endl;
    return 0;
}

此程序输出2.5

您可以通过使用using namespace std;来避免意外结果,但我建议不这样做,因为它通常被认为是不良实践,并且因为您必须搜索using指令才能知道abs()表示int重载还是double重载。


我也遇到了同样的问题。对我来说,abs()和std::abs()都会丢失小数部分,但是fabs()可以正常工作。你有什么想法吗? - jmoraal
@jmoraal 抱歉,我不知道有什么原因会导致这种情况...可能是旧编译器吗?您可以将此作为问题发布,并包括所有细节,例如代码和使用的编译器。 - alain

3

我的 Visual C++ 2008 不知道该从 long double fabs(long double)float fabs(float) 或者 double fabs(double) 中选择哪一个。

在语句 double i = -9; 中,编译器会知道 -9 应该被转换为 double,因为 i 的类型是 double


abs() 声明在 stdlib.h 中,它处理的是 int 值。

fabs() 声明在 math.h 中,它处理的是 double 值。


1
在C++中,absfabs都在<cmath>头文件中:http://en.cppreference.com/w/cpp/numeric/math/fabs - NathanOliver
2
@NathanOliver std::absstd::fabs 是。其他的可以,但不一定要。 - juanchopanza

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