質問
はありまisnan()機能しているのでしょうか。
PS.:私 MinGW の場合と違い).
またこの解を用いisnan()から <math.h>
, るには存在しない <cmath>
, 私た #include
ングです。
解決
IEEE標準によると、NaN値は、それらを含む比較は、の常にの偽である奇数性質を持っています。これは、フロートFのために、f != f
はfはNaNであるののみの場合はtrueになりますされています。
以下に、いくつかのコメントとして指摘されている、なお、全てのコンパイラがこれを尊重しません。
IEEE浮動小数点を使用するように主張して任意のコンパイラの場合、このトリックのはずがの仕事。しかし、私はそれは、の練習での動作することを保証することはできません。疑問がある場合は、お使いのコンパイラに確認します。
他のヒント
ありません isnan()
機能をご利用の現在のC++の標準図書館があります。紹介されました C99 として定義してい マクロ りません。要素の標準ライブラリで定義されるC99あなたの現在のC++の標準ISO/IEC14882:1998年も更新がISO/IEC14882:2003年.
2005年に技術研究報告1を提案した。のTR1な互換性C99C++.にもかかわらずれていない公式を採用してC++の標準は、多くの(GCC4.0+ または Visual C++9.0+ C++実装によって提供TR1、すべての、または一部(Visual C++9.0提供いたしませんC99mathます。
まTR1することができ、 cmath
含まれC99のような isnan()
, isfinite()
, など。な定義としての機能、マクロ、通常 std::tr1::
名前空間にも多数の実装につGCC4+LinuxまたはXCode Mac OS X10.5+)注入されていない std::
, ので、 std::isnan
で定義されています。
また、一部の実装ではC++がC99 isnan()
マクロ用のC++を含むを通じて cmath
または math.h
何の原因となりますの混乱および開発者とので活動しています。
に関する注意Viusal C++、これまで見てきたように、提供する事は御座いません std::isnan
も std::tr1::isnan
, 、その延長として定義される関数 _isnan()
して利用されるようになりました Visual C++6.0
にXCodeであっても楽しいのではないでしょうか。このように、GCC4+を定義し std::isnan
.のための古いバージョンのコンパイラおよび図書館のXCodeう(こちら 関連した討論)こなかったがチェック自分のつながりを保ちつつ、両者の機能の定義 __inline_isnand()
インテルおよび __isnand()
電力ます。
第一ソリューション:ご利用の場合はC++11
このたりのビットの新展開:が重要であることを知 std::isnan()
の一部であるC++11
概要
定義されるヘッダー <cmath>
bool isnan( float arg ); (since C++11)
bool isnan( double arg ); (since C++11)
bool isnan( long double arg ); (since C++11)
されているかどうかを判定します指定された浮動小数点数argが非数(NaN
).
パラメータ
arg
:浮動小数点値
戻り値
true
まargが NaN
, false
その他
参考
http://en.cppreference.com/w/cpp/numeric/math/isnan
なお、このと互換性がない高速-数学のご利用の場合はg++、下記を参照してくださいその他ご提案します。
他のソリューション:の場合を用いたC++11準拠したツール
のためのC99、C、このメソッドの実装では、マクロ isnan(c)
ることで、int値を返します。の種類 x
は、float、double、長しまいます。
各種ベンダーはありませんしたものではありませ機能 isnan()
.
のはずの携帯をチェックする NaN
は、IEEE754ィ NaN
するものではなく、そのもの:すなわち x == x
する場合はfalse x
ている NaN
.
しかし最後のオプションが正常に動作しない場合があり毎にコンパイラおよび一部の設定(最適化、特に設定で、昨リゾートで必ず確認してください、ビットパターンの---
もあり ヘッダのみが図書館 に存在することにブーストして整ツールへの浮動小数点データ型
#include <boost/math/special_functions/fpclassify.hpp>
し、下記の機能:
template <class T> bool isfinite(T z);
template <class T> bool isinf(T t);
template <class T> bool isnan(T t);
template <class T> bool isnormal(T t);
時間に余裕があればして全体の数学のツールキットからブースでは、多くの有用なツールは急速に増えています。
も処理時に浮かび非浮動小数点ですが、良いアイデアの 数値変換.
3 "公式" の方法がありますPOSIXの isnan
マクロは、C ++ 0xのの isnan
関数テンプレートを、またはVisual C ++の _isnan
機能の。
残念ながら、それはそれらのどれを使用することを検出するために、むしろ非現実的です。
そして、残念ながら、あなたはNaNを持つIEEE 754表現を持っているかどうかを検出するための信頼できる方法はありません。標準ライブラリは公式な方法(numeric_limits<double>::is_iec559
)を提供しています。しかし、そのようなgと実際のコンパイラで++それを台無します。
理論では、1つはそれを台無し++例えばG ++やVisual Cなどが、コンパイラ、単にx != x
する を使用することができます。
特定ののNaN bitpatterns の、仮定(いくつかの点で、うまくいけば強制!)は、IEEE 754のような特定の表現のためのテスト、最後になる。
<時間>編集: "などgとコンパイラ++ ...ネジそのアップ" の例として、
考えます#include <limits>
#include <assert.h>
void foo( double a, double b )
{
assert( a != b );
}
int main()
{
typedef std::numeric_limits<double> Info;
double const nan1 = Info::quiet_NaN();
double const nan2 = Info::quiet_NaN();
foo( nan1, nan2 );
}
++ gのコンパイル(TDM-2 MINGW32)4.4.1:
C:\test> type "C:\Program Files\@commands\gnuc.bat" @rem -finput-charset=windows-1252 @g++ -O -pedantic -std=c++98 -Wall -Wwrite-strings %* -Wno-long-long C:\test> gnuc x.cpp C:\test> a && echo works... || echo !failed works... C:\test> gnuc x.cpp --fast-math C:\test> a && echo works... || echo !failed Assertion failed: a != b, file x.cpp, line 6 This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. !failed C:\test> _
のstd :: ISNANありますが、私はmingwのがないかどうかわからないんだけど。
ここにあなたのコンパイラが標準機能を持っていない場合は動作するはずの小さな機能があります:
bool custom_isnan(double var)
{
volatile double d = var;
return d != d;
}
あなたはでテストするnumeric_limits<float>::quiet_NaN( )
標準ライブラリで定義されてlimits
を使用することができます。 double
のために定義された別の定数があります。
#include <iostream>
#include <math.h>
#include <limits>
using namespace std;
int main( )
{
cout << "The quiet NaN for type float is: "
<< numeric_limits<float>::quiet_NaN( )
<< endl;
float f_nan = numeric_limits<float>::quiet_NaN();
if( isnan(f_nan) )
{
cout << "Float was Not a Number: " << f_nan << endl;
}
return 0;
}
これはすべてのプラットフォーム上で動作するか私はLinux上でG ++でテストとして、私は、知りません。
あなたはisnan()
機能を使用することができますが、Cの数学ライブラリを含める必要があります。
#include <cmath>
この関数は、C99の一部であるとして、それはどこでも利用できません。あなたのベンダーが機能を提供しない場合は、互換性のために、独自のバリアントを定義することができます。
inline bool isnan(double x) {
return x != x;
}
nan防止
私の答えは な遡及をチェック nan
.使用 予防 チェック部の形 0.0/0.0
です。
#include <float.h>
float x=0.f ; // I'm gonna divide by x!
if( !x ) // Wait! Let me check if x is 0
x = FLT_MIN ; // oh, since x was 0, i'll just make it really small instead.
float y = 0.f / x ; // whew, `nan` didn't appear.
nan
結果から操作 0.f/0.f
, や 0.0/0.0
. nan
は恐宿敵の安定性的なヘルプオーサリング-ツールが必要な検出され を防止 非常に厳1.の性質 nan
ることから通常の番号:
nan
は、毒性(5*nan
=nan
)nan
するものではなく、何もないもの(nan
!=nan
)nan
以何かnan
!> 0)nan
は以下のもの(nan
!< 0)
最後の2つの特性に掲載されているカウンターの論理となりますの奇行動のコードに依存するとの比較 nan
番号(第3回最終財が奇数の時にはしっかり確保して欲しいですが、しょせっち x != x ?
コード(いない場合の確認のためのnan(unreliably))).
自分のコードであることに気が付き nan
価値観が作用が困難になります。注どのようにして ない の場合 inf
または -inf
. (-inf
< 0)を返します TRUE
, ( 0 < inf
)がTRUEを返すと、もてなし-inf
< inf
)はTRUEを返します。そこでの私の経験の動作をコードする しばしば 依然として希望).
い下nan
したいものが下 0.0/0.0
として扱う必要がありますが特別な場合, がんによるものでなければなので期待はます。
上記の例では、この結果0.f/FLT_MIN
) 0
, は基本的に自由とします。い 0.0/0.0
成 HUGE
です。なので、
float x=0.f, y=0.f, z;
if( !x && !y ) // 0.f/0.f case
z = FLT_MAX ; // biggest float possible
else
z = y/x ; // regular division.
このように上がった 0.f
, inf
これは良い/非破壊挙動として上記の実際).
この 整数部門による0る実行時例外.で必ず確認のための整数部門により0になります。か 0.0/0.0
静かに評価し nan
なまれ、怠けることのないチェック 0.0/0.0
となどが挙げられる。
1 チェック nan
通 x != x
ることもあり信頼できない(x != x
ている控除後では一部の最適化コンパイラがIEEEの遵守、具体的には、 -ffast-math
スイッチます。
次のコードは、NANの定義(すべての指数ビットが設定され、少なくとも1つの分数ビットのセット)を使用してはsizeof(int型)=はsizeof(フロート)= 4.詳細はウィキペディアにNANを検索できることを前提としています。
bool IsNan( float value )
{
return ((*(UINT*)&value) & 0x7fffffff) > 0x7f800000;
}
としてのC++14多数の試験方法の場合、浮動小数点数 value
であるものがあります。
これらの方法は、 することを確認しますビット の数の表現
作品を確実にという私の答えです。特に、 std::isnan
とが提案したチェック v != v
, な作業を確実に利用すべきではありませんねコードが停止し正常に動作していると判断したときに浮動小数点の最適化が必要であり、それをコンパイラになる。この状況を変更可能なコンパイラでコンパイルすることに則したが、この問題となったのは6年目の答えになります。
約6年間の私の答えたの選択したソリューションはその問題については、してくれました。すが、最近は高upvoted答案の信頼できない v != v
試験は選択されています。そのため追加されたことより最新の答え(いのC++11およびC++14基準C++17にした。
の方法は主にチェックのための難しさ、C++14:
std::isnan(value) )
を標準ライブラリとは、なんらかの意味でC++11.isnan
が明らかに矛盾する Posixにはマクロの名前と同じだが、練習う機会を設けていきたいと思います。主な問題は、 その時の浮動小数点演算最適化され、その後少なくとも一つのコンパイラは、g++,std::isnan
を返しますfalse
のための引数がNaN.(fpclassify(value) == FP_NAN) )
から、同じ問題としてstd::isnan
, つではない。(value != value) )
おすすめ多くの人が答える。から、同じ問題としてstd::isnan
, ( は信頼性に欠ける。(value == Fp_info::quiet_NaN()) )
この試験は標準の挙動は検出されないNaNs、その 最適化行動かを検出することができNaNsより最適化されたコードだけで比較する bitlevel表現を直接、も合わせるもう一つの方法 カバーを標準国連を最適化した動きを確実に検出しものがあります。残念ながら しかったで動作しない確実です。(ilogb(value) == FP_ILOGBNAN) )
から、同じ問題としてstd::isnan
, つではない。isunordered(1.2345, value) )
から、同じ問題としてstd::isnan
, つではない。is_ieee754_nan( value ) )
このな機能を標準装備しました。このチェックのビットによると、IEEE754 標準装備。で完全に信頼性の が このコードは、幾分システムに依存します。
以下のテストコードを"成功"するかどうかを表報告Nanらしさの値です。ほとんどの表現がこの措置の成功により、目標の検出NaNsみNaNsに対応する標準意味論。のための (value == Fp_info::quiet_NaN()) )
表現し、標準の挙動がうまくいきませんでしNaN-検出器である。
#include <cmath> // std::isnan, std::fpclassify
#include <iostream>
#include <iomanip> // std::setw
#include <limits>
#include <limits.h> // CHAR_BIT
#include <sstream>
#include <stdint.h> // uint64_t
using namespace std;
#define TEST( x, expr, expected ) \
[&](){ \
const auto value = x; \
const bool result = expr; \
ostringstream stream; \
stream << boolalpha << #x " = " << x << ", (" #expr ") = " << result; \
cout \
<< setw( 60 ) << stream.str() << " " \
<< (result == expected? "Success" : "FAILED") \
<< endl; \
}()
#define TEST_ALL_VARIABLES( expression ) \
TEST( v, expression, true ); \
TEST( u, expression, false ); \
TEST( w, expression, false )
using Fp_info = numeric_limits<double>;
inline auto is_ieee754_nan( double const x )
-> bool
{
static constexpr bool is_claimed_ieee754 = Fp_info::is_iec559;
static constexpr int n_bits_per_byte = CHAR_BIT;
using Byte = unsigned char;
static_assert( is_claimed_ieee754, "!" );
static_assert( n_bits_per_byte == 8, "!" );
static_assert( sizeof( x ) == sizeof( uint64_t ), "!" );
#ifdef _MSC_VER
uint64_t const bits = reinterpret_cast<uint64_t const&>( x );
#else
Byte bytes[sizeof(x)];
memcpy( bytes, &x, sizeof( x ) );
uint64_t int_value;
memcpy( &int_value, bytes, sizeof( x ) );
uint64_t const& bits = int_value;
#endif
static constexpr uint64_t sign_mask = 0x8000000000000000;
static constexpr uint64_t exp_mask = 0x7FF0000000000000;
static constexpr uint64_t mantissa_mask = 0x000FFFFFFFFFFFFF;
(void) sign_mask;
return (bits & exp_mask) == exp_mask and (bits & mantissa_mask) != 0;
}
auto main()
-> int
{
double const v = Fp_info::quiet_NaN();
double const u = 3.14;
double const w = Fp_info::infinity();
cout << boolalpha << left;
cout << "Compiler claims IEEE 754 = " << Fp_info::is_iec559 << endl;
cout << endl;;
TEST_ALL_VARIABLES( std::isnan(value) ); cout << endl;
TEST_ALL_VARIABLES( (fpclassify(value) == FP_NAN) ); cout << endl;
TEST_ALL_VARIABLES( (value != value) ); cout << endl;
TEST_ALL_VARIABLES( (value == Fp_info::quiet_NaN()) ); cout << endl;
TEST_ALL_VARIABLES( (ilogb(value) == FP_ILOGBNAN) ); cout << endl;
TEST_ALL_VARIABLES( isunordered(1.2345, value) ); cout << endl;
TEST_ALL_VARIABLES( is_ieee754_nan( value ) );
}
結果は、g++(注していますか?標準の挙動 (value == Fp_info::quiet_NaN())
はうまくいきませんでしNaN-検出器をかけて食べるという習慣があり非常に多くの実践的関心はここ):
[C:\my\forums\so\282 (detect NaN)] > g++--version|find"++" g++ (x86_64-win32-sjlj-rev1, Built by MinGW-W64 project) 6.3.0 [C:\my\forums\so\282 (detect NaN)] > g++foo.cpp &&a Compiler claims IEEE 754 = true v = nan, (std::isnan(value)) = true Success u = 3.14, (std::isnan(value)) = false Success w = inf, (std::isnan(value)) = false Success v = nan, ((fpclassify(value) == 0x0100)) = true Success u = 3.14, ((fpclassify(value) == 0x0100)) = false Success w = inf, ((fpclassify(value) == 0x0100)) = false Success v = nan, ((value != value)) = true Success u = 3.14, ((value != value)) = false Success w = inf, ((value != value)) = false Success v = nan, ((value == Fp_info::quiet_NaN())) = false FAILED u = 3.14, ((value == Fp_info::quiet_NaN())) = false Success w = inf, ((value == Fp_info::quiet_NaN())) = false Success v = nan, ((ilogb(value) == ((int)0x80000000))) = true Success u = 3.14, ((ilogb(value) == ((int)0x80000000))) = false Success w = inf, ((ilogb(value) == ((int)0x80000000))) = false Success v = nan, (isunordered(1.2345, value)) = true Success u = 3.14, (isunordered(1.2345, value)) = false Success w = inf, (isunordered(1.2345, value)) = false Success v = nan, (is_ieee754_nan( value )) = true Success u = 3.14, (is_ieee754_nan( value )) = false Success w = inf, (is_ieee754_nan( value )) = false Success [C:\my\forums\so\282 (detect NaN)] > g++foo.cpp -ffast-数学&&a Compiler claims IEEE 754 = true v = nan, (std::isnan(value)) = false FAILED u = 3.14, (std::isnan(value)) = false Success w = inf, (std::isnan(value)) = false Success v = nan, ((fpclassify(value) == 0x0100)) = false FAILED u = 3.14, ((fpclassify(value) == 0x0100)) = false Success w = inf, ((fpclassify(value) == 0x0100)) = false Success v = nan, ((value != value)) = false FAILED u = 3.14, ((value != value)) = false Success w = inf, ((value != value)) = false Success v = nan, ((value == Fp_info::quiet_NaN())) = true Success u = 3.14, ((value == Fp_info::quiet_NaN())) = true FAILED w = inf, ((value == Fp_info::quiet_NaN())) = true FAILED v = nan, ((ilogb(value) == ((int)0x80000000))) = true Success u = 3.14, ((ilogb(value) == ((int)0x80000000))) = false Success w = inf, ((ilogb(value) == ((int)0x80000000))) = false Success v = nan, (isunordered(1.2345, value)) = false FAILED u = 3.14, (isunordered(1.2345, value)) = false Success w = inf, (isunordered(1.2345, value)) = false Success v = nan, (is_ieee754_nan( value )) = true Success u = 3.14, (is_ieee754_nan( value )) = false Success w = inf, (is_ieee754_nan( value )) = false Success [C:\my\forums\so\282 (detect NaN)] > _
結果とサンプルシミュレーション:
[C:\my\forums\so\282 (detect NaN)] > cl/nologo-2>&1|find"++" Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23725 for x86 [C:\my\forums\so\282 (detect NaN)] > cl foo.cpp 日&&b foo.cpp Compiler claims IEEE 754 = true v = nan, (std::isnan(value)) = true Success u = 3.14, (std::isnan(value)) = false Success w = inf, (std::isnan(value)) = false Success v = nan, ((fpclassify(value) == 2)) = true Success u = 3.14, ((fpclassify(value) == 2)) = false Success w = inf, ((fpclassify(value) == 2)) = false Success v = nan, ((value != value)) = true Success u = 3.14, ((value != value)) = false Success w = inf, ((value != value)) = false Success v = nan, ((value == Fp_info::quiet_NaN())) = false FAILED u = 3.14, ((value == Fp_info::quiet_NaN())) = false Success w = inf, ((value == Fp_info::quiet_NaN())) = false Success v = nan, ((ilogb(value) == 0x7fffffff)) = true Success u = 3.14, ((ilogb(value) == 0x7fffffff)) = false Success w = inf, ((ilogb(value) == 0x7fffffff)) = true FAILED v = nan, (isunordered(1.2345, value)) = true Success u = 3.14, (isunordered(1.2345, value)) = false Success w = inf, (isunordered(1.2345, value)) = false Success v = nan, (is_ieee754_nan( value )) = true Success u = 3.14, (is_ieee754_nan( value )) = false Success w = inf, (is_ieee754_nan( value )) = false Success [C:\my\forums\so\282 (detect NaN)] > cl foo.cpp /Feb/fp:高速&&b foo.cpp Compiler claims IEEE 754 = true v = nan, (std::isnan(value)) = true Success u = 3.14, (std::isnan(value)) = false Success w = inf, (std::isnan(value)) = false Success v = nan, ((fpclassify(value) == 2)) = true Success u = 3.14, ((fpclassify(value) == 2)) = false Success w = inf, ((fpclassify(value) == 2)) = false Success v = nan, ((value != value)) = true Success u = 3.14, ((value != value)) = false Success w = inf, ((value != value)) = false Success v = nan, ((value == Fp_info::quiet_NaN())) = false FAILED u = 3.14, ((value == Fp_info::quiet_NaN())) = false Success w = inf, ((value == Fp_info::quiet_NaN())) = false Success v = nan, ((ilogb(value) == 0x7fffffff)) = true Success u = 3.14, ((ilogb(value) == 0x7fffffff)) = false Success w = inf, ((ilogb(value) == 0x7fffffff)) = true FAILED v = nan, (isunordered(1.2345, value)) = true Success u = 3.14, (isunordered(1.2345, value)) = false Success w = inf, (isunordered(1.2345, value)) = false Success v = nan, (is_ieee754_nan( value )) = true Success u = 3.14, (is_ieee754_nan( value )) = false Success w = inf, (is_ieee754_nan( value )) = false Success [C:\my\forums\so\282 (detect NaN)] > _
総括として取りまとめました結果、直接試験のビットレベルの表現を使用し、 is_ieee754_nan
機能が定義されたこの試験プログラム信頼すべての場合の両方g++やVisual C++.
補足:
投稿遅いという現象が起こるのだろうなると認識していることができる試験のためのNaNとされたものについては、 他の答え ここでは、 ((value < 0) == (value >= 0))
.ってしまったのか事とVisual C++でも失敗したg++'s -ffast-math
オプションです。直bitpattern試作品も確実です。
inline bool IsNan(float f)
{
const uint32 u = *(uint32*)&f;
return (u&0x7F800000) == 0x7F800000 && (u&0x7FFFFF); // Both NaN and qNan.
}
inline bool IsNan(double d)
{
const uint64 u = *(uint64*)&d;
return (u&0x7FF0000000000000ULL) == 0x7FF0000000000000ULL && (u&0xFFFFFFFFFFFFFULL);
}
sizeof(int)
は4であり、sizeof(long long)
が8である場合、これは動作します。
は、実行時にそれが唯一の比較で、鋳物は、任意の時間がかかることはありません。それはちょうど平等をチェックするために、比較フラグの設定を変更します。
NaNのための特定のIEEE表現に依存しない可能性のある解決策は、次のようであろうと使用しました
template<class T>
bool isnan( T f ) {
T _nan = (T)0.0/(T)0.0;
return 0 == memcmp( (void*)&f, (void*)&_nan, sizeof(T) );
}
私として解決策は、それが明示的にインラインで十分なので、高速で行うためのマクロである可能性があります。 また、任意のfloat型のために動作します。これは、値が数値でない場合に値自体に等しいされていない場合のみであるという事実に基づかます。
#ifndef isnan
#define isnan(a) (a != a)
#endif
(!X = x)は常にNaN(非等-ffast-数学オプションを使用している場合など)のために保証されていない、私が使用してきたことを考えると、
#define IS_NAN(x) (((x) < 0) == ((x) >= 0))
の数字は、数がより少なく、またゼロ以上でもない場合ので、実際には、このチェックのみ通過する、<0と> = 0の両方にすることはできません。これは基本的にはまったく番号、またはNaNではありません。
ご希望の場合は、また、これを使用することができます:
#define IS_NAN(x) (!((x)<0) && !((x)>=0)
私はこれがそのように、あなたの走行距離は異なる場合があり、しかし-ffast-数学の影響を受けているかどうかはわかりません。
この作品ます:
#include <iostream>
#include <math.h>
using namespace std;
int main ()
{
char ch='a';
double val = nan(&ch);
if(isnan(val))
cout << "isnan" << endl;
return 0;
}
出力:ISNAN
最高の真のクロスプラットフォームのアプローチは、NaNをチェックするために労働組合を使用すると、二重のビットパターンをテストするだろうと私には思えます。
私は徹底的にこのソリューションをテストしていない、とのビットパターンでの作業のより効率的な方法があるかもしれないが、私はそれが動作するはずだと思います。
#include <stdint.h>
#include <stdio.h>
union NaN
{
uint64_t bits;
double num;
};
int main()
{
//Test if a double is NaN
double d = 0.0 / 0.0;
union NaN n;
n.num = d;
if((n.bits | 0x800FFFFFFFFFFFFF) == 0xFFFFFFFFFFFFFFFF)
{
printf("NaN: %f", d);
}
return 0;
}
IEEE標準は言います
指数はすべて1
sあるとき
そして
仮数は、ゼロではありません
番号はNaN
です。
二重は、符号ビット、1
指数ビットと11
仮数ビット52
あります。
ビットのチェックを行います。
あなたは関係なく、-ffast-math
コンパイラオプションの働きはNaNと無限大のためにチェックするための非常に高速な方法を、持つことができx86-64でオン。 (f != f
、std::isnan
、std::isinf
常にfalse
と-ffast-math
を得た)。
はNaN、無限と有限の数値のためのテストは簡単に最大の指数をチェックすることにより行うことができます。無限がゼロ仮数と最大指数であり、NaNは最大指数と非ゼロの仮数です。私達はちょうど符号ビットを取り除くと指数に最上位ビットを作るために左シフトすることができるように指数は、最上位の符号ビットの後の次のビットに格納され、何のマスキング(operator&
)は必要ありません。
static inline uint64_t load_ieee754_rep(double a) {
uint64_t r;
static_assert(sizeof r == sizeof a, "Unexpected sizes.");
std::memcpy(&r, &a, sizeof a); // Generates movq instruction.
return r;
}
static inline uint32_t load_ieee754_rep(float a) {
uint32_t r;
static_assert(sizeof r == sizeof a, "Unexpected sizes.");
std::memcpy(&r, &a, sizeof a); // Generates movd instruction.
return r;
}
constexpr uint64_t inf_double_shl1 = UINT64_C(0xffe0000000000000);
constexpr uint32_t inf_float_shl1 = UINT32_C(0xff000000);
// The shift left removes the sign bit. The exponent moves into the topmost bits,
// so that plain unsigned comparison is enough.
static inline bool isnan2(double a) { return load_ieee754_rep(a) << 1 > inf_double_shl1; }
static inline bool isinf2(double a) { return load_ieee754_rep(a) << 1 == inf_double_shl1; }
static inline bool isfinite2(double a) { return load_ieee754_rep(a) << 1 < inf_double_shl1; }
static inline bool isnan2(float a) { return load_ieee754_rep(a) << 1 > inf_float_shl1; }
static inline bool isinf2(float a) { return load_ieee754_rep(a) << 1 == inf_float_shl1; }
static inline bool isfinite2(float a) { return load_ieee754_rep(a) << 1 < inf_float_shl1; }
std
セグメントからisinf
とisfinite
負荷のdouble/float
バージョン2つの.data
定数をし、最悪の場合には、それらは2つのデータ・キャッシュ・ミスを引き起こす可能性があります。上記のバージョンはinf_double_shl1
とinf_float_shl1
定数はアセンブリ命令に即値オペランドとしてエンコードされます、すべてのデータをロードしません。
高速化isnan2
はわずか2アセンブリ命令です。
bool isnan2(double a) {
bool r;
asm(".intel_syntax noprefix"
"\n\t ucomisd %1, %1"
"\n\t setp %b0"
"\n\t .att_syntax prefix"
: "=g" (r)
: "x" (a)
: "cc"
);
return r;
}
は、いずれかの引数がNaNである場合は ucomisd
の命令は、パリティフラグを設定しているという事実を使用します。これは何のstd::isnan
オプションが指定されていないとき-ffast-math
がどのように機能するかである。
これは二重の範囲内で、それをされてチェックすることにより、Visual Studioの中で無限大ともNaNのを検出します:
//#include <float.h>
double x, y = -1.1; x = sqrt(y);
if (x >= DBL_MIN && x <= DBL_MAX )
cout << "DETECTOR-2 of errors FAILS" << endl;
else
cout << "DETECTOR-2 of errors OK" << endl;
状態上記のコメントが!= g ++およびいくつかの他のコンパイラでは動作しませんが、このトリックが必要として。それは効率的ではないかもしれないが、それはまだ方法です。
bool IsNan(float a)
{
char s[4];
sprintf(s, "%.3f", a);
if (s[0]=='n') return true;
else return false;
}
基本的には、グラムで++(私はかかわらず、他の人わからないです)のprintfプリント「ナン」%dまたは%.F形式上の変数が有効な整数/浮動小数点数ではない場合。したがって、このコードは
(「ナン」のように)「N」であると文字列の最初の文字をチェックされます