C ++で無限および不定の値をどのようにチェックしますか?
-
03-07-2019 - |
質問
私のプログラムでは、通常、値をゼロで割ると無限が生じます。ゼロをゼロで割ると、不確定になります。 C ++で無限値および不定値をどのようにチェックしますか?
C ++では、無限は1.#INFで表されます。不定は-1。#INDで表されます。問題は、変数が無限か不確定かをテストする方法です。無限大のチェックは比較的簡単です。特定のC ++で無限大の定義を見つけます。私の場合(VS2003)、std :: numeric_limits :: infinity()です。 <!> quot; limits <!> quot;を含める必要があります。それを使用するために。この無限値を変数に割り当て、その値が無限であるかどうかを確認するために、ある値と比較できます。
不確定値は、ややトリッキーです。不定値を他の値と比較できないためです。比較するとfalseが返されます。このプロパティを使用して、不定値をそれ自体と比較することで検出できます。 aValという二重変数があるとします。通常の状態では、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
、または< a href = "http://msdn.microsoft.com/en-us/library/aa246882(VS.60).aspx" rel = "noreferrer"> _fpclass
。
ただし、C ++ 11対応の標準ライブラリとコンパイラにアクセスできる場合は、 std::isnan
および std::isinf
。
他のヒント
C ++ 03はC99の isnan を提供しませんが、 isinf マクロ、C ++ 11は標準化関数として提供します。厳密なC ++ 03の代わりにC ++ 11を使用できる場合、これらはマクロを回避することにより、よりクリーンなオプションになります。コンパイラ組み込み関数およびプラットフォーム依存の関数。
C ++ 11の std::isfinite
は、true
を返しますinf
およびnan
を除くすべての値。 !isfinite
は、1回のショットで無限および不定の値をチェックする必要があります。
厳密にはC ++ 03の一部ではありませんが、コンパイラが標準<!> lt; math.h <!> gt;の新しいC99機能の一部を提供する場合ヘッダーファイルの場合、次の<!> quot; function-like macros <!> quot ;: isfinite
、isinf
、isnan
にアクセスできます。その場合、これらはこれらのチェックを実行する最も簡単で安全な方法です。
これらを厳密な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
に注意)
C99またはPOSIXなどからのisfinite
があります。
それを行うためのハック的な方法の1つは、x-x == 0
をテストすることです。 x
が無限またはNaNの場合、x-x
はNaNであるため比較は失敗し、0
が有限の場合、<=>は<=>であり、比較は成功します。ただし、<=>を使用するか、このテストを<=>のような関数/マクロにパッケージ化することをお勧めします。そうすれば、いつでもすべてを取り除くことができます。
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