Pregunta

En mis programas el infinito suele surgir cuando se divide un valor por cero.Me pongo indeterminado cuando divido cero entre cero.¿Cómo se comprueban valores infinitos e indeterminados en C++?

En C++, el infinito está representado por 1.#INF.Indeterminado está representado por -1.#IND.El problema es cómo comprobar si una variable es infinita o indeterminada.Comprobar el infinito es relativamente sencillo:Encontrarás la definición de infinito en tu C++ particular.Para mi caso (VS2003), es std::numeric_limits::infinity().Tienes que incluir "límites" para poder usarlo.Puede asignar este valor infinito a una variable y compararlo con algún valor para verificar si ese valor es infinito.

Indeterminado es un poco complicado, porque no se puede comparar un valor indeterminado con algún otro valor.Cualquier comparación devuelve falso.Puede utilizar esta propiedad para detectar un valor indeterminado comparándolo consigo mismo.Digamos que tienes una variable doble llamada aVal.En condiciones normales, aVal != aVal devuelve falso.Pero si el valor es indeterminado, aIndVal != aIndVal devuelve verdadero.Esta extraña situación no está presente para valores infinitos, es deciraInfVal != aInfVal siempre devuelve falso.

Aquí hay dos funciones que se pueden usar para verificar valores indeterminados e infinitos:

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

¿Existen mejores formas de realizar estas comprobaciones? ¿Me estoy perdiendo algo?

¿Fue útil?

Solución

Para Visual Studio, usaría _isnan y _finite , o tal vez < a href = "http://msdn.microsoft.com/en-us/library/aa246882(VS.60).aspx" rel = "noreferrer"> _fpclass .

Pero si tiene acceso a una biblioteca y compilador estándar compatible con C ++ 11, puede usar std::isnan y std::isinf .

Otros consejos

Aunque C++03 no proporciona C99 isnan y isinf macros, C++ 11 los estandariza proporcionándolos como funciones.Si puede usar C++ 11, en lugar del estricto C++ 03, entonces estas serían opciones más limpias, al evitar macros. compilador incorporado y funciones dependientes de la plataforma.

C ++ 11 std::isfinite devoluciones true para todos los valores excepto inf y nan;entonces !isfinite debe comprobar si hay valores infinitos e indeterminados de una sola vez.

Aunque no es estrictamente una parte de C ++ 03, si su compilador proporciona algunas de las nuevas características C99 del estándar < math.h > archivo de encabezado, entonces puede tener acceso a las siguientes " macros de función " ;: isfinite, isinf, isnan. Si es así, esta sería la forma más fácil y segura de realizar estas comprobaciones.

También puede usarlos como una solución estricta de C ++ solamente. Realmente no ofrecen más que la solución del OP, excepto seguridad adicional mediante el uso de rasgos de tipo y quizás el menor impulso de velocidad en el caso 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();
}

(cuidado con el static_assert hecho a sí mismo

hay isfinite de C99 o POSIX o algo así, creo.

Una forma hacky de hacerlo es probar x-x == 0;si x es infinito o NaN, entonces x-x es NaN por lo que la comparación falla, mientras que si x es finito, entonces x-x es 0 y la comparación tiene éxito.Recomiendo usar isfinite, sin embargo, o empaquetar esta prueba en una función/macro llamada algo así como isfinite para que puedas deshacerte de todo cuando llegue el 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

esto también podría funcionar (pero implica llamar a exp () y probar la igualdad de dobles):

if (exp(-x)==0.) ... then x is inf
if (exp(x)==0.)  ... then x is -inf
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top