Domanda

Nei miei programmi l'infinito di solito sorge quando un valore è diviso per zero. Divento indeterminato quando divido zero per zero. Come controllate i valori infiniti e indeterminati in C ++?

In C ++, l'infinito è rappresentato da 1. # INF. Indeterminato è rappresentato da -1. # IND. Il problema è come verificare se una variabile è infinita o indeterminata. Controllare l'infinito è relativamente semplice: trovi la definizione di infinito nel tuo particolare C ++. Nel mio caso (VS2003), è std :: numeric_limits :: infinity (). Devi includere & Quot; limits & Quot; per usarlo. Puoi assegnare questo valore infinito a una variabile e confrontarlo con un valore per verificare se quel valore è infinito.

Indeterminato è un po 'complicato, perché non è possibile confrontare un valore indeterminato con un altro valore. Qualsiasi confronto restituisce false. È possibile utilizzare questa proprietà per rilevare un valore indeterminato confrontandolo con se stesso. Supponiamo che tu abbia una doppia variabile chiamata aVal. In condizioni normali, aVal! = AVal restituisce false. Ma se il valore è indeterminato, aIndVal! = AIndVal restituisce true. Questa strana situazione non è presente per valori infiniti, ovvero aInfVal! = AInfVal restituisce sempre false.

Ecco due funzioni che possono essere utilizzate per verificare valori indeterminati e infiniti:

#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())
}

Esistono modi migliori per questi controlli, mi manca qualcosa?

È stato utile?

Soluzione

Per Visual Studio userei _isnan e _finite , o forse < a href = "http://msdn.microsoft.com/en-us/library/aa246882(VS.60).aspx" rel = "noreferrer"> _fpclass .

Ma se si ha accesso a una libreria e compilatore standard in grado di supportare C ++ 11, è possibile utilizzare std::isnan e std::isinf .

Altri suggerimenti

Sebbene C ++ 03 non fornisca isnan di C99 e isinf macro , C ++ 11 standardizza fornendoli come funzioni . Se puoi usare C ++ 11, invece del rigoroso C ++ 03, queste sarebbero opzioni più pulite, evitando le macro, compilatore integrato e funzioni dipendenti dalla piattaforma.

C ++ 11 std::isfinite restituisce true per tutti i valori tranne inf e nan; quindi !isfinite dovrebbe verificare la presenza di valori infiniti e indeterminati in un colpo solo.

Sebbene non sia strettamente parte di C ++ 03, se il compilatore fornisce alcune delle nuove funzionalità C99 dello standard < math.h > file di intestazione, quindi potresti avere accesso ai seguenti " macro simili a funzioni " ;: isfinite, isinf, isnan. In tal caso, questi sarebbero il modo più semplice e sicuro per eseguire questi controlli.

Puoi anche usarli come una soluzione rigorosa per soli C ++. In realtà non offrono più della soluzione del PO, tranne una maggiore sicurezza attraverso l'uso di tratti di tipo e forse il più piccolo aumento di velocità nel caso di 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();
}

(attenzione agli autocostruiti static_assert)

C'è isfinite da C99 o POSIX o qualcosa che penso.

Un modo hacker per farlo è testare x-x == 0; se x è infinito o NaN, quindi x-x è NaN, quindi il confronto fallisce, mentre se 0 è finito, <=> è <=> e il confronto ha esito positivo. Ti consiglio di usare <=>, o di impacchettare questo test in una funzione / macro chiamata qualcosa come <=> in modo da poter sbarazzarti di tutto quando sarà il momento.

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

questo potrebbe anche funzionare (ma implica call to exp () e test di uguaglianza dei doppi):

if (exp(-x)==0.) ... then x is inf
if (exp(x)==0.)  ... then x is -inf
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top