web-dev-qa-db-fra.com

Comment vérifier les valeurs infinies et indéterminées en C++?

Dans mes programmes, l'infini se produit généralement lorsqu'une valeur est divisée par zéro. Je deviens indéterminé quand je divise zéro par zéro. Comment vérifier les valeurs infinies et indéterminées en C++?

En C++, l'infini est représenté par 1. # INF. Indéterminé est représenté par -1. # IND. Le problème est de savoir comment tester si une variable est infinie ou indéterminée. Vérifier l'infini est relativement simple: vous trouvez la définition de l'infini dans votre C++ particulier. Pour mon cas (VS2003), c'est std :: numeric_limits :: infinity (). Vous devez inclure des "limites" pour pouvoir l'utiliser. Vous pouvez affecter cette valeur infinie à une variable et la comparer à une valeur afin de vérifier si cette valeur est infinie.

Indéterminé est un peu délicat, car vous ne pouvez pas comparer une valeur indéterminée à une autre valeur. Toute comparaison retourne false. Vous pouvez utiliser cette propriété pour détecter une valeur indéterminée en la comparant à elle-même. Disons que vous avez une double variable appelée aVal. Dans des conditions normales, aVal! = AVal renvoie false. Mais si la valeur est indéterminée, aIndVal! = AIndVal renvoie true. Cette situation étrange n’est pas présente pour les valeurs infinies, c’est-à-dire aInfVal! = AInfVal renvoie toujours false.

Voici deux fonctions qui peuvent être utilisées pour vérifier les valeurs indéterminées et infinies:

#include "limits.h"
#include "math.h"

bool isIndeterminate(const double pV)
{
    return (pV != pV);
} 

bool isInfinite(const double pV)
{
    return (fabs(pV) == std::numeric_limits::infinity())
}

Existe-t-il de meilleurs moyens de procéder à ces vérifications?

28
Samil

Pour Visual Studio, je voudrais utiliser _isnan et _finite , ou peut-être _fpclass .

Mais si vous avez accès à une bibliothèque et à un compilateur standard compatibles C++ 11, vous pouvez utiliser std::isnan et std::isinf .

17
dalle

Bien que C++ 03 ne fournisse pas les isnan et isinf macros de C99, C++ 11 les standardise en les fournissant comme fonctions . Si vous pouvez utiliser C++ 11, au lieu de C++ 03 strict, il s'agira d'options plus propres, en évitant les macros, les fonctions intégrées au compilateur } et dépendantes de la plate-forme.

std::isfinite de C++ 11 renvoie true pour toutes les valeurs sauf inf et nan; donc !isfinite devrait vérifier les valeurs infinies et indéterminées d’un seul coup.

9
legends2k

Vous pouvez également les utiliser comme une solution strictement C++ uniquement. Ils n'offrent pas vraiment plus que la solution de l'OP, sauf une sécurité accrue grâce à l'utilisation de caractères de type et peut-être la plus petite augmentation de vitesse dans le cas de is_inf.

template <bool> struct static_assert;
template <> struct static_assert<true> { };

template<typename T>
inline bool is_NaN(T const& x) {
    static_cast<void>(sizeof(static_assert<std::numeric_limits<T>::has_quiet_NaN>));
    return std::numeric_limits<T>::has_quiet_NaN and (x != x);
}

template <typename T>
inline bool is_inf(T const& x) {
    static_cast<void>(sizeof(static_assert<std::numeric_limits<T>::has_infinity>));
    return x == std::numeric_limits<T>::infinity() or x == -std::numeric_limits<T>::infinity();
}

(méfiez-vous de l'auto-fabrication static_assert)

3
Konrad Rudolph

Bien que cela ne fasse pas strictement partie de C++ 03, si votre compilateur fournit certaines des nouvelles fonctionnalités C99 du fichier d’en-tête standard <math.h>, vous pouvez accéder aux "macros de type fonction" suivantes: isfinite, isinfisnan. Si tel est le cas, il s’agit du moyen le plus simple et le plus sûr d’effectuer ces vérifications.

3
CB Bailey

Il y a isfinite de C99 ou POSIX ou quelque chose que je pense.

Une façon astucieuse de le faire est de tester x-x == 0; Si x est infini ou NaN, alors x-x est NaN et la comparaison échoue. Si x est fini, alors x-x est 0 et la comparaison aboutit. Je vous conseillerais toutefois d'utiliser isfinite ou de regrouper ce test dans une fonction/macro appelée quelque chose comme isfinite afin de pouvoir vous en débarrasser le moment venu.

2
tmyklebu
if (x!=x)              ... then x is nan
if (x>0 && x/x != x/x) ... then x is +inf
if (x<0 && x/x != x/x) ... then x is -inf

cela pourrait aussi fonctionner (mais implique l'appel à exp () et le test de l'égalité des doublons):

if (exp(-x)==0.) ... then x is inf
if (exp(x)==0.)  ... then x is -inf
0
Azrael