C99規格ではmath.hにもマクロや関数が追加されています.しかし,現在の評価環境であるGCC2.95.3では対応できていません.C99規格の説明をするために,しばらくの間Cygwin環境のお世話になることにします.GCCのバージョンは3.2です.
● HUGE_VALについて
GCC2.95でもHUGE_VALは定義されていました.
今回HUGE_VALF/HUGE_VALLも規格に追加されたのですが,GCC3.2の環境でもまだ対応できていません.
ちなみに,HUGE_VALはdouble型の無限大,HUGE_VALFはfloat型,HUGE_VALLはlong doubleの無限大を表す定数です(リスト4,リスト5).
〔リスト4〕HUGE_VALの例(test127.c)
|
/*
*HUGE_VALについて
*/
#include <stdio.h>
#include <math.h>
main()
{
double a = HUGE_VAL;
printf("%G\n",a);
}
|
|
〔リスト5〕生成されたアセンブラコード(test127.s)
|
.file "test127.c"
.def ___main; .scl 2; .type 32; .endef
.text
LC0:
.ascii "%G\12\0"
.align 2
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp, %ebp
subl $40, %esp
andl $-16, %esp
movl $0, %eax
movl %eax, -12(%ebp)
movl -12(%ebp), %eax
call __alloca
call ___main
movl __imp____infinity, %eax
movl 4(%eax), %edx
movl (%eax), %eax
movl %eax, -8(%ebp)
movl %edx, -4(%ebp)
movl $LC0, (%esp)
movl -8(%ebp), %eax
movl -4(%ebp), %edx
movl %eax, 4(%esp)
movl %edx, 8(%esp)
call _printf
leave
ret
.def _printf; .scl 2; .type 32; .endef
|
|
以下は実行結果です.
$ ./test127
Inf
このように,無限大を表すInfが表示されます.
● INFINITY
無限大を表すfloat型の定数ですが,GCC3.2でも定義されていません(リスト6).コンパイル結果は以下のとおりです.
〔リスト6〕INFINITYの例(test128.c)
|
/*
*INFINITYについて
*/
#include <stdio.h>
#include <math.h>
main()
{
float f = NAN;
printf("%f\n",f);
}
|
|
$ gcc test128.c -o test128
test128.c: In function `main':
test128.c:8: `INFINITY' undeclared (first use in this function)
test128.c:8: (Each undeclared identifier is reported only once
test128.c:8: for each function it appears in.)
● NAN
not a numberの意味です.0.0/0.0の値をNANと名付けますが,GCC3.2の環境でも定義されていません.
● fpclassify(x)
これは関数型マクロです.引き数xがNANか無限大,または通常の数値,ゼロかを判定し,結果を,それぞれFP_NAN,FP_
INFINITE,FP_NAN,FP_NORMAL,FP_ZEROとして返します.FP_SUBNORMALという定数もあるはずですが,GCC3.2では存在しません(リスト7).
〔リスト7〕fpclassifyの例(test129.c)
|
/*
*fpclassifyについて
*/
#include <stdio.h>
#include <math.h>
main()
{
if ( fpclassify(0.0/0.0) == FP_NAN )
{
printf("0.0/0.0 = not a number\n");
}
if ( fpclassify(1.0/0.0) == FP_INFINITE )
{
printf("1.0/0.0 = 無限大\n");
}
if ( fpclassify(1.1/1.5) == FP_NORMAL )
{
printf("1.1/1.5 = 通常の数値\n");
}
}
|
|
実行結果は以下のとおりです.
$ ./test129
0.0/0.0 = not a number
1.0/0.0 = 無限大
1.1/1.5 = 通常の数値
● isfinite(x)
この関数型マクロは,引き数が無限大かNANの場合にゼロを返します(リスト8).実行結果は以下のとおりです.
〔リスト8〕isfiniteの例(test130.c)
|
/*
*isfiniteについて
*/
#include <stdio.h>
#include <math.h>
main()
{
if ( isfinite(0.0/0.0) )
{
printf("isfinite(0.0/0.0) は 真");
}
if ( isfinite(1.0/0.0) )
{
printf("isfinite(1.0/0.0) は 真");
}
if ( isfinite(1.1/1.5) )
{
printf("isfinite(1.1/1.5) は 真");
}
}
|
|
$ ./test130
isfinite(0.0/0.0) は 真
● isinf(x)
この関数型マクロは,引き数が無限大の場合にゼロを返します(リスト9).実行結果は次のとおりです.
〔リスト9〕isinfの例(test131.c)
|
/*
*isintについて
*/
#include <stdio.h>
#include <math.h>
main()
{
if ( isinf(0.0/0.0) )
{
printf("isinf(0.0/0.0) は 真");
}
if ( isinf(1.0/0.0) )
{
printf("isinf(1.0/0.0) は 真");
}
if ( isinf(1.1/1.5) )
{
printf("isinf(1.1/1.5) は 真");
}
}
|
|
$ ./test131
isinf(1.0/0.0) は 真
● isnan(x)
この関数型マクロは,引き数がNANの場合にゼロを返します(リスト10).実行結果は以下のとおりです.
〔リスト10〕isnanの例(test132.c)
|
/*
*isnanについて
*/
#include <stdio.h>
#include <math.h>
main()
{
if ( isnan(0.0/0.0) )
{
printf("isnan(0.0/0.0) は 真");
}
if ( isnan(1.0/0.0) )
{
printf("isnan(1.0/0.0) は 真");
}
if ( isnan(1.1/1.5) )
{
printf("isnan(1.1/1.5) は 真");
}
}
|
|
$ ./test132
isnan(0.0/0.0) は 真
以上のように,math.hで定義されている関数の種類が増えました.
それはfloat,long doubleに対応するようになったからです.同一の関数でもdouble,float,long double対応と3種類あることが多くなりました.
しかし,GCC3.2ではlong doubleには対応できていません.
詳しくはmath.hをご覧ください.
|