web-dev-qa-db-fra.com

Quelle est la différence entre les abs et les fabs?

J'ai vérifié la différence entre abs et fabs sur python ici

Si je comprends bien, il existe certaines différences entre la vitesse et les types passés, mais ma question portait sur le c ++ natif sur V.S.

En ce qui concerne le V.S ..__, j’ai essayé ce qui suit sur Visual Studio 2013 (v120):

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

Donc, fabs(-9) cela me donnera une erreur de compilation, mais quand j’ai essayé de faire ce qui suit:

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

D'après ce que j'ai compris du premier code, il ne compilera pas car fabs(-9) a besoin d'un double et le compilateur n'a pas pu convertir -9 en -9.0, mais dans le second code, le compilateur convertira i=-9 en i=-9.0 lors de la compilation afin que fabs(i) fonctionne correctement .

Une meilleure explication?

Une autre chose, pourquoi le compilateur ne peut pas accepter fabs(-9) et convertir la valeur int en double automatiquement comme ce que nous avons en c #?

[*]:

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)   
16
Hazem Abdullah

En C++, std::abs est surchargé pour les types entiers signés et à virgule flottante. std::fabs ne traite que des types à virgule flottante (avant C++ 11). Notez que le std:: est important, la fonction C ::abs qui est généralement disponible pour des raisons héritées ne gérera que int!

Le problème avec 

float f2= fabs(-9);

n'est pas qu'il n'y a pas de conversion de int (le type de -9) en double, mais que le compilateur ne sait pas quelle conversion choisir (int -> float, double, long double) puisqu'il existe un std::fabs pour chacun de ces trois. Votre solution de contournement indique explicitement au compilateur d'utiliser la conversion int -> double, de sorte que l'ambiguïté disparaisse.

C++ 11 résout ce problème en ajoutant double fabs( Integral arg ); qui renverra la abs de tout type entier converti en double. Apparemment, cette surcharge est également disponible en mode C++ 98 avec libstdc ++ et libc ++.

En général, utilisez simplement std::abs, cela fera le bon choix. ( Piège intéressant souligné par @Shafik Yaghmour . Les types entiers non signés font des choses amusantes en C++.)

15
Baum mit Augen

Mon Visual C++ 2008 ne savait pas lequel choisir parmi long double fabs(long double), float fabs(float) ou double fabs(double).

Dans l'instruction double i = -9;, le compilateur saura que -9 doit être converti en double car le type de i est double.


abs() est déclaré dans stdlib.h et il traitera la valeur int.

fabs() est déclaré dans math.h et il traitera la valeur double.

2
MikeCAT

Avec C++ 11, utiliser abs() seul est très dangereux:

#include <iostream>
#include <cmath>

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

Ce programme génère donc 2. ( Voir en direct )

Toujours utiliser std::abs():

#include <iostream>
#include <cmath>

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

Ce programme génère 2.5.

Vous pouvez éviter le résultat inattendu avec using namespace std;, mais je vous le déconseillerai, car c'est généralement considéré comme une mauvaise pratique et vous devez rechercher la directive using pour savoir si abs() correspond à la surcharge int ou à la surcharge double.

1
alain