浮動小数の非数と無限大について気になったので、それについての簡単な実験とメモ。

libavutil/mathematics.h では、非数と無限大が以下で定義されている。

#ifndef NAN
#define NAN (0.0/0.0)
#endif
#ifndef INFINITY
#define INFINITY (1.0/0.0)
#endif

しかし、これは MSVC ではコンパイルできない (gcc では問題ない)。

test.cpp

#include <stdio.h>

int main(void)
{
	printf("(0.0/0.0): %f\n", (0.0/0.0));
	printf("(1.0/0.0): %f\n", (1.0/0.0));
	return 0;
}
$ cl /nologo test.cpp
test.cpp(5) : error C2124: 除算、剰余演算が 0 で行われています。
$ g++ test.cpp -o test
$ ./test
(0.0/0.0): -1.#IND00
(1.0/0.0): 1.#INF00

C++ の標準クラスに、非数と無限大を求める関数がある。
こちらは MSVC でも問題なくコンパイルできる。

test2.cpp

#include <stdio.h>
#include <limits>

int main(void)
{
	printf("std::numeric_limits<double>::quiet_NaN(): %f\n",
		std::numeric_limits<double>::quiet_NaN());
	printf("std::numeric_limits<double>::signaling_NaN(): %f\n",
		std::numeric_limits<double>::signaling_NaN());
	printf("std::numeric_limits<double>::infinity(): %f\n",
		std::numeric_limits<double>::infinity());
	return 0;
}
$ cl /nologo test2.cpp
$ test2
std::numeric_limits::quiet_NaN(): 1.#QNAN0
std::numeric_limits::signaling_NaN(): 1.#QNAN0
std::numeric_limits::infinity(): 1.#INF00
$ g++ test2.cpp -o test2
$ ./test2
std::numeric_limits::quiet_NaN(): 1.#QNAN0
std::numeric_limits::signaling_NaN(): 1.#SNAN0
std::numeric_limits::infinity(): 1.#INF00

無限大は 1.#INF00 1 つだが、非数は、-1.#IND00/1.#QNAN0/1.#SNAN0 の 3 つが出てきてしまった。
違いはよく分からない。

math.h に以下の関数があるが、C99 で MSVC では使えない。

isfinite 引数の値が有限の値かどうかを判定する
isinf 引数の値が無限大かどうかを判定する
isnan 引数の値が NaN (非数) かどうかを判定する

代わりに MSVC には _finite/_isnan がある。
できれば、共通にしてもらいたいものだが。

また、やはり C99 だが、nan という関数もあるようだ。

【参考】

numeric_limits – C++ Reference
C言語関数辞典 – math.h
_finite
_isnan