web-dev-qa-db-ja.com

double変数のinf(および|または)NaNをチェックする方法

次のコードを検討してください。

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

template<class T>
bool IsNaN(T t)
{
    return t != t;
}

int main(int argc, char**argv)
{
    double d1, d2;
    sscanf(argv[1], "%f", &d1);
    sscanf(argv[2], "%f", &d2);

    double dRes = d1/d2;

    cout << "dRes = " << dRes << "\n";

    if(IsNaN(dRes))
        cout << "Is NaN\n";
    else
        cout << "Not NaN\n";

}

いくつかの質問:

  1. 引数として0と0を渡すと、dRes = inf。でも期待していたdRes = NaNまたはそのようなもの。
  2. NaNはdouble変数で表現できますか?それについて、変数はありますか?
  3. D1、d2、dResのデータ型をintに変更して0と0を渡すと、Floating exception。違いはなんですか?
  4. 変数の値がinfと等しいかどうかを確認する方法は?
20
nakiya
  1. scanf()を使用する場合、doubleは_%lf_ではなく_%f_を使用して読み取る必要があります。 _%f_は入力を32ビットのfloatに変換するため、変数の最初の32ビットは無効なデータで埋められ、最後の32ビットはガベージとして残されます。

  2. はい。 _#include <limits>_、 、[std::numeric_limits<double>::quiet_NaN() 。一部のコンパイラ(gccなど)では、 NANマクロを_<cmath>_ で提供しています。

  3. 整数型にはNaNや無限大はありません。整数をゼロで除算すると、 例外(SIGFPE) が発生します。

  4. _#include <cmath>_、次に std::isinf(x)std::isfinite(x) を使用して、xがNaNまたはInfinityでないことを確認します。

29
kennytm

関数fpclassifyを使用すると、すべての特殊なケースの浮動小数点値を検査できます。

C99以降、<math.h>はマクロとして、関数のファミリとして<cmath>に、floatdouble、およびlong double C++ 11以降、オーバーロードされた名前std::fpclassify

cppreferenceには いい例 があります

0
Ben Voigt