2015-11-16 6 views
14

ich den Unterschied zwischen abs und fabs auf Python geprüft hereWas ist der Unterschied zwischen `abs` vs` fabs` ist in (C++)

Wie ich es verstehen sind einige Unterschiede in Bezug auf die Geschwindigkeit und die übergebenen Typen, aber mein Frage im Zusammenhang mit nativem C++ auf VS

bezüglich der V.S. Ich habe versucht, die folgenden auf Visual Studio 2013 (v120):

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

So fabs(-9) es gibt mir einen Compiler-Fehler, aber wenn ich versuchte, die folgendes zu tun:

double i = -9; 
float f2= fabs(i); // This will work fine 

Was ich aus dem ersten Code zu verstehen, dass es wird nicht kompiliert, weil fabs(-9) ein Double benötigen, und der Compiler nicht -9 zu -9.0 konvertieren konnte, aber im zweiten Code wird der Compiler i=-9 in i=-9.0 zur Kompilierzeit umwandeln, so fabs(i) wird gut funktionieren.

Eine bessere Erklärung?

Eine andere Sache, warum der Compiler fabs(-9) nicht akzeptieren kann und den int-Wert automatisch so umwandeln, wie wir in C# haben?

[*]: 

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) 
+0

Keine Compiler Fehler hier: http://coliru.stacked-crooked.com/a/80c5484bda892461 – NathanOliver

Antwort

11

In C++ ist std::abs sowohl für vorzeichenbehaftete ganzzahlige als auch Gleitkommatypen überladen. std::fabs behandelt nur Fließkommatypen (vor C++ 11). Beachten Sie, dass die std:: wichtig ist, die C-Funktion ::abs, die aus Legacy-Gründen allgemein verfügbar ist, wird nur int behandeln!

Das Problem mit

float f2= fabs(-9); 

ist nicht, dass es keine Umwandlung von int ist (die Art der) zu double, aber dass der Compiler nicht weiß, welche Umwandlung zu holen (int ->float, double , long double), da es für jeden dieser drei einen std::fabs gibt. Ihre Problemumgehung weist den Compiler explizit an, die int ->double-Konvertierung zu verwenden, damit die Mehrdeutigkeit verschwindet.

C++ 11 löst dies durch Hinzufügen von double fabs(Integral arg);, die die abs eines beliebigen Ganzzahl-Typs in double konvertiert zurückgibt. Offensichtlich ist diese Überladung auch im C++ 98-Modus mit libstdC++ und libC++ verfügbar.

Im Allgemeinen verwenden Sie einfach std::abs, es wird das Richtige tun. (.. Interesting pitfall wies darauf hin, durch @Shafik Yaghmour Unsigned Integer-Typen lustige Dinge tun in C++)

+1

* Im Allgemeinen einfach std :: abs, es wird das Richtige tun. * ... sehen [Ist std :: abs (0u) schlecht gebildet?] (Http://stackoverflow.com/q/29750946/1708801) –

+0

@ShafikYaghmour Interessant, das habe ich nie erlebt. Es ist erstaunlich, wie viele Ungerundete Ganzzahlen in C++ verursachen. Die "richtige" Implementierung, die die vorzeichenlose Ganzzahl in "double" umwandelt, ist nicht das, was ich erwarten würde, dass dieser Code TBH ausführt. –

+0

Versteh mich nicht falsch, das ist eine gute Antwort, ich bin zufällig darauf gestoßen und es ist gut, sich dessen bewusst zu sein, besonders da es Implementierungsvarianz gibt und es immer noch offen ist. –

2

My Visual C++ 2008 wusste nicht, was zu Wahl von long double fabs(long double), float fabs(float) oder double fabs(double).

In der Erklärung double i = -9;, wird der Compiler weiß, dass zu double umgewandelt werden sollte, weil die Art der idouble ist.


abs() in stdlib.h erklärt und es wird mit int Wert beschäftigen.

fabs() ist in math.h deklariert und es wird sich mit double Wert befassen.

+1

in C++ 'abs' und' fabs' sind beide in '': http://en.cppreference.com/ w/cpp/numerisch/math/fabs – NathanOliver

+1

@NathanOliver 'std :: abs' und' std :: fabs' sind. Die anderen können, müssen aber nicht sein. – juanchopanza

1

Mit C++ 11, mit abs() allein ist sehr gefährlich:

#include <iostream> 
#include <cmath> 

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

Dieses Programm gibt 2 als Ergebnis. (See it live)

Immer std::abs():

#include <iostream> 
#include <cmath> 

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

Dieses Programm gibt 2.5.

Sie können das unerwartete Ergebnis mit using namespace std; vermeiden, aber ich würde adwise dagegen, weil es in der Regel schlechte Praxis betrachtet wird, und weil sie die using Richtlinie suchen müssen wissen, ob abs() bedeuten die int Überlastung oder die double Überlastung .

Verwandte Themen