Wann verwende ich fabs und wann reicht es aus, std :: abs zu verwenden?

100

Ich gehe davon aus absund fabsverhalte mich bei der Verwendung anders math.h. Aber wenn ich nur cmathund benutze std::abs, muss ich std::fabsoder verwenden fabs? Oder ist das nicht definiert?

Mathematik
quelle

Antworten:

124

In C ++ ist die Verwendung immer ausreichend std::abs. Es ist für alle numerischen Typen überladen.

In C absfunktioniert nur mit ganzen Zahlen, und Sie benötigen fabsGleitkommawerte. Diese sind in C ++ (zusammen mit der gesamten C-Bibliothek) verfügbar, müssen jedoch nicht verwendet werden.

Mike Seymour
quelle
Ist dies auf jeder Plattform der Fall? Esp. Windows und Mac OS X? Oder ist es zumindest im C ++ Standard?
Mathe
3
@brubelsabs: ja. In C ++ ist keine separate Fabs-Funktion erforderlich, da C ++ über eine Funktionsüberladung verfügt (abs kann für zahlreiche Typen definiert werden und ist in C ++ enthalten). Dies wird auch durch den Standard garantiert. Wenn Sie einen veralteten Compiler finden, der älter als 10 Jahre ist, finden Sie möglicherweise einen, der ihn nicht unterstützt.
stinky472
1
Es ist in dem C ++ Standard so ist es der Fall , auf jeder Plattform mit einem anständigen Compiler, einschließlich Windows und Mac OS X. Paragraf 26.5 besagt , dass, zusätzlich zu der intVersion aus der C - Bibliothek gibt es Überlastungen für long, float, doubleund long double. Abschnitt 26.2.7 definiert auch eine Überlastung für complex.
Mike Seymour
6
Wenn Sie das vergessen std::und nur verwenden abs, funktioniert Ihr Code unter Windows wie erwartet, verwendet jedoch die intVersion unter Linux, die unglaublich schwer zu debuggen sein kann.
Adversus
" alle numerischen Typen" [Zitieren erforderlich]. Ich kann int, long, long long, std :: intmax_t, float, double, long double sehen. Keine Kurz- oder Zeichenversionen (oder nicht signierte Versionen), die ich sehen kann.
user673679
23

Es ist immer noch in Ordnung, fabsfür doubleund floatArgumente zu verwenden. Ich bevorzuge dies, weil es sicherstellt , dass das Verhalten für Gleitkomma-Eingaben gleich bleibt , wenn ich versehentlich das std::ausziehe abs.

Ich habe gerade 10 Minuten damit verbracht, genau dieses Problem zu debuggen, weil ich den Fehler gemacht habe, absanstelle von zu verwenden std::abs. Ich nahm an, dass das using namespace std;schließen würde, std::absaber es tat es nicht und verwendete stattdessen die C-Version.

Wie auch immer, ich glaube, es ist gut, fabsanstelle von absGleitkomma-Eingaben zu verwenden, um Ihre Absicht klar zu dokumentieren.

Alan Turing
quelle
2
Das ist komisch. Ihr Anruf sollte mehrdeutig (und damit ein Fehler) sein, oder?
Nick
Sollten Sie fabsf nicht für float verwenden? Ich denke also nicht, dass sie identisch sind.
Nick
Hüten Sie sich vor Android NDK g ++, es tritt auch die Funktion c abs () anstelle von std :: abs () ab. Im Visual Studio c ++ - Compiler zeigt abs jedoch immer auf std :: abs ().
Southton
@Nick, ich glaube, ich stimme dir zu: Ich scheine das Verhalten von Alan Turing nicht zu verstehen, dh für mich std::absscheint die Überlastung absbeim Aufruf immer aufgerufen zu werden (und nicht die C-Version von ), abssolange dies using namespace std;am erklärt wird Anfang. Ich weiß allerdings nicht, ob dies compilerspezifisch ist.
MaviPranav
@Nick ist kein Fehler, da ein Funktionsname übereinstimmt. Es ist die Implementierung definiert, welche ausgewählt wird.
Pato Sandaña
11

Es gibt noch einen weiteren Grund, std::fabsexplizit für Gleitkomma-Eingaben zu empfehlen .

Wenn Sie vergessen, <cmath> einzuschließen, std::abs(my_float_num)können Sie std::abs(int)stattdessen sein std::abs(float). Es ist schwer zu bemerken.

Kenichi Hidai
quelle
1

"abs" und "fabs" sind nur für C ++ - Float-Typen identisch, wenn sie ohne mehrdeutige Überlastungsnachrichten übersetzt werden können.

Ich benutze g ++ (g ++ - 7). Zusammen mit der Verwendung von Vorlagen und insbesondere bei der Verwendung von mpreal gibt es Fälle mit harten "mehrdeutigen Überlastungs" -Nachrichten -abs(static_cast<T>(x)) wird nicht immer gelöst. Wenn abs mehrdeutig ist, besteht die Möglichkeit, dass Fabs wie erwartet funktionieren. Für sqrt habe ich keine so einfache Flucht gefunden.

Seit Wochen kämpfe ich hart mit C ++ "nicht existierenden Problemen". Ich aktualisiere ein altes C ++ - Programm auf C ++ 14, um mehr und bessere Vorlagen als bisher zu verwenden. Oft kann derselbe Vorlagenparameter ein beliebiger Standard-Float oder ein komplexer Typ oder ein Klassentyp sein. Long Double wirkte jedoch etwas vernünftiger als andere Typen. Alles funktionierte und ich hatte zuvor mpreal aufgenommen. Dann habe ich meinen Standard-Float-Typ auf mpreal gesetzt und eine Flut von Syntaxfehlern erhalten. Das führte zu Tausenden von mehrdeutigen Überlastungen, z. B. für abs und sqrt, und nach unterschiedlichen Lösungen. Einige benötigten überladene Hilfefunktionen, jedoch außerhalb einer Vorlage. Musste einzeln tausend Verwendungen von 0.0L und 1.0L durch den exakten Konstantentyp mit Zero oder One oder einem type_cast ersetzen - eine automatische Konvertierungsdefinition ist aufgrund von Mehrdeutigkeiten nicht möglich.

Bis Mai fand ich die vorhandenen impliziten Konvertierungen sehr schön. Aber viel einfacher wäre es ohne, und typsparende Konstanten mit sicheren expliziten type_casts für jeden anderen Standardkonstantentyp zu haben.

BS3
quelle