私のプログラムでは、通常、値がゼロで除算されると無限大が発生します。ゼロをゼロで除算すると、不確定になります。 C++で無限値と不確定値を確認するにはどうすればよいですか?
C++では、無限大は1.#INFで表されます。不確定は-1。#INDで表されます。問題は、変数が無限または不確定であるかどうかをテストする方法です。無限大のチェックは比較的簡単です。特定のC++で無限大の定義を見つけます。私の場合(VS2003)、それはstd :: numeric_limits :: infinity()です。使用するには「制限」を含める必要があります。この無限の値を変数に割り当て、その値をある値と比較して、その値が無限であるかどうかを確認できます。
不確定な値を他の値と比較することはできないため、不確定なものは少しトリッキーです。比較するとfalseが返されます。このプロパティを使用して、それ自体と比較することにより、不確定な値を検出できます。 aValという名前のdouble変数があるとします。通常の状態では、aVal!= aValはfalseを返します。ただし、値が不定の場合、aIndVal!= aIndValはtrueを返します。この奇妙な状況は無限値には存在しません。つまり、aInfVal!= aInfValは常にfalseを返します。
以下は、不確定値と無限値をチェックするために使用できる2つの関数です。
#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())
}
これらのチェックのためのより良い方法はありますか、何か不足していますか?
Visual Studioでは _isnan
および _finite
、またはおそらく _fpclass
。
ただし、C++ 11対応の標準ライブラリとコンパイラにアクセスできる場合は、 std::isnan
および std::isinf
。
C++ 03はC99の isnan および isinfmacrosを提供していませんが、C++ 11は、それらを functions として提供することで標準化します。厳密なC++ 03の代わりにC++ 11を使用できる場合、マクロ、 コンパイラ組み込み 、およびプラットフォームに依存する関数を回避することにより、これらはよりクリーンなオプションになります。
C++ 11の std::isfinite
は、true
とinf
を除くすべての値に対してnan
を返します。そう !isfinite
は、1回のショットで無限および不確定の値をチェックする必要があります。
これらを厳密なC++のみのソリューションとして使用することもできます。タイプトレイトの使用によるセキュリティの追加とis_inf
の場合のおそらく最も小さな速度向上を除いて、これらは実際にはOPのソリューション以上のものを提供しません。
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();
}
(自作static_assert
にご注意ください)
厳密にはC++ 03の一部ではありませんが、コンパイラが標準の<math.h>ヘッダーファイルの新しいC99機能の一部を提供している場合、次の「関数のようなマクロ」にアクセスできる場合があります。isfinite
、isinf
、isnan
。もしそうなら、これらはこれらのチェックを実行する最も簡単で安全な方法でしょう。
C99やPOSIXなどのisfinite
があります。
それを行う1つのハックな方法は、テストすることですx-x == 0
; x
が無限またはNaNの場合、x-x
はNaNであるため、比較は失敗しますが、x
が有限の場合、x-x
は0
と比較すると成功します。ただし、isfinite
を使用するか、このテストをisfinite
のような関数/マクロにパッケージ化して、時間の経過とともにすべてを取り除くことができるようにすることをお勧めします。
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
これも機能する可能性があります(ただし、exp()の呼び出しとdoubleの等価性のテストが含まれます)。
if (exp(-x)==0.) ... then x is inf
if (exp(x)==0.) ... then x is -inf