math.hのマクロ

 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をご覧ください.

Copyright 2003 岸 哲夫

Copyright 1997-2017 CQ Publishing Co.,Ltd.

 

NEW記事内インデックス    連載インデックスはこちら   Interfaceのトップ
追加された関数やマクロについて
◆math.hのマクロ
stdio.hに追加されたいくつかの関数/stdlibに追加されたいくつかの関数
C99規格で新規に追加された標準ライブラリ