web-dev-qa-db-fra.com

Quand est-ce que j'utilise les fabs et quand est-il suffisant d'utiliser std :: abs?

Je suppose que abs et fabs se comportent différemment lorsqu’on utilise math.h. Mais quand j'utilise seulement cmath et std::abs, dois-je utiliser std::fabs ou fabs? Ou n'est-ce pas défini?

94
math

En C++, il suffit toujours d'utiliser std::abs; il est surchargé pour tous les types numériques.

En C, abs ne fonctionne que sur les entiers et vous avez besoin de fabs pour les valeurs à virgule flottante. Celles-ci sont disponibles en C++ (avec toute la bibliothèque C), mais il n'est pas nécessaire de les utiliser.

120
Mike Seymour

Vous pouvez toujours utiliser fabs pour les arguments double et float. Je préfère cela parce que si j’arrache accidentellement le std:: _ du abs, que le comportement reste le même pour les entrées à virgule flottante.

Je viens de passer 10 minutes à déboguer ce problème, à cause de ma propre erreur d’utiliser abs au lieu de std::abs. J'ai supposé que le using namespace std;d'en déduirait std::abs _ mais ce n’était pas le cas et utilisait plutôt la version C.

Quoi qu'il en soit, je pense qu'il est bon d'utiliser fabs au lieu de abs pour les entrées à virgule flottante afin de documenter clairement votre intention.

22
Alan Turing

Il y a une autre raison de recommander explicitement std::fabs Pour les entrées à virgule flottante.

Si vous oubliez d'inclure <cmath>, votre std::abs(my_float_num) peut être std::abs(int) au lieu de std::abs(float). C'est difficile à remarquer.

10
Kenichi Hidai

"abs" et "fabs" ne sont identiques que pour les types float C++, quand ils peuvent être traduits sans messages de surcharge ambigus.

J'utilise g ++ (g ++ - 7). Avec l'utilisation des modèles et en particulier lors de l'utilisation de mpreal, il y a des cas avec des messages "de surcharge ambiguës" - abs(static_cast<T>(x)) ne résout pas toujours cela. Lorsque les abdos sont ambigus, il est probable que les fabs fonctionnent comme prévu. Pour ça, je n'ai trouvé aucune évasion aussi simple.

Depuis des semaines, je me bats pour le C++ "pas de problèmes existants". Je suis en train de mettre à jour un ancien programme C++ vers C++ 14 pour utiliser davantage et mieux les modèles qu'auparavant. Souvent, le même paramètre de modèle peut correspondre à n'importe quel type standard ou float standard ou type de classe. Pourquoi jamais, long double agit un peu plus sensible que les autres types. Tout fonctionnait et j'avais déjà inclus mpreal. Ensuite, je mettais mon type float par défaut à mpreal et j'ai eu un déluge d’erreurs de syntaxe. Cela a donné des milliers de surcharges ambiguës, par exemple pour abs et sqrt, implorant différentes solutions. Certains avaient besoin de fonctions d'aide surchargées, mais en dehors d'un modèle. Devait remplacer individuellement mille utilisations de 0,0L et 1,0L par le type de constante exact utilisant Zero ou One ou un type_cast - la définition de conversion automatique est impossible à cause des ambiguïtés.

Jusqu'au mois de mai, j'ai trouvé l'existence de conversions implicites très agréable. Mais il serait beaucoup plus simple d’en avoir, et d’avoir des constantes de type avec des types_casts explicites sûrs vers tout autre type de constante standard.

1
BS3