当前位置: C语言 -- 标准库 -- <math.h> -- math_errhandling

math_errhandling宏


概要:

#define math_errhandling value //value值由实现定义。


描述:

该宏会扩展为int类型的常量表达式,其值为MATH_ERRNOMATH_ERREXCEPT或者(MATH_ERRNO | MATH_ERREXCEPT),表示通过errno和引发浮点异常报告错误的宏。

ISO/IEC 9899:2018标准未明确说明math_errhandling是宏,还是具有外部链接的标识符。

如果宏math_errhandling定义是禁止的,或者程序定义了名为math_errhandling的标识符,其行为是未定义的。

如果表达式(math_errhandling & MATH_ERREXCEPT)为非0值,实现应在<fenv.h>头文件中定义宏FE_DIVBYZEROFE_INVALIDFE_OVERFLOW


ISO/IEC 9899:2018标准第7.12.1 Treatment of error conditions节规定了数学函数错误情况的处理,归纳如下表所示:

错误 处理
MATH_ERRNO

域错误(domain error):当且仅当输入参数不在数学函数定义的域内时,才会发生域错误,例如:sqrt(-5.0)。

errno设置为EDOM①⑤

极点错误(pole error):也称奇点或者无穷大,当且仅当有限参数接近极限时,数学函数将具有无限结果,从而发生极点错误,例如:log(0.0)。

errno设置为ERANGE①⑤

溢出(overflow):如果数学函数的结果是有限的,但太大,指定类型如果没有异常舍入就无法表示该结果,这时会发生溢出,例如:exp(1000.0)。

errno设置为ERANGE①⑤

下溢(underflow):如果数学函数的结果是有限的,但太小,指定类型如果没有异常舍入就无法表示该结果,这时会发生下溢,例如:exp(-1000.0)。

errno设置为ERANGE③⑤
MATH_ERREXCEPT

域错误(domain error):当且仅当输入参数不在数学函数定义的域内时,才会发生域错误,例如:sqrt(-5.0)。

引发浮点异常FE_INVALID

极点错误(pole error):也称奇点或者无穷大,当且仅当有限参数接近极限时,数学函数将具有无限结果,从而发生极点错误,例如:log(0.0)。

引发浮点异常FE_DIVBYZERO

溢出(overflow):如果数学函数的结果是有限的,但太大,指定类型如果没有异常舍入就无法表示该结果,这时会发生溢出,例如:exp(1000.0)。

引发浮点异常FE_OVERFLOW

下溢(underflow):如果数学函数的结果是有限的,但太小,指定类型如果没有异常舍入就无法表示该结果,这时会发生下溢,例如:exp(-1000.0)。

引发浮点异常FE_UNDERFLOW

如果表达式(math_errhandling & MATH_ERRNO)是非0值,errno将被设置为与错误对应的值。

如果表达式(math_errhandling & MATH_ERREXCEPT)是非0值,将引发对应的浮点异常。

如果表达式(math_errhandling & MATH_ERRNO)是非0值,errno是否设置为ERANGE将由实现定义。

如果表达式(math_errhandling & MATH_ERREXCEPT)是非0值,是否引发浮点异常FE_UNDERFLOW将由实现定义。

如果发生域错误、极点错误、溢出或者下溢,并且表达式(math_errhandling & MATH_ERRNO)值等于0errno应设置为与错误对应的值或者保持不变。

如果没有发生上述错误,无论math_errhandling如何设置,errno都应保持不变。


范例:
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
/*宏math_errhandling范例*/

#include <errno.h>
#include <fenv.h>
#include <math.h>
#include <stdio.h>

#pragma STDC FENV_ACCESS ON

/*判断错误类型的函数。*/
void showErrno(void)
{
    printf("Error: ");

    if(math_errhandling & MATH_ERRNO)
    {
        switch(errno)
        {
            case EDOM: puts("EDOM");
                break;
            case ERANGE: puts("ERANGE");
                break;
            default: puts("Unknown error");
                break;
        }
    }
}

/*判断浮点异常的函数。*/
void showExceptions(void)
{
    printf("Exceptions: ");

    if(math_errhandling & MATH_ERREXCEPT)
    {
        if(fetestexcept(FE_DIVBYZERO))
            printf("FE_DIVBYZERO");
        if(fetestexcept(FE_INVALID))
            printf("FE_INVALID");
        if(fetestexcept(FE_OVERFLOW))
            printf("FE_OVERFLOW");
        if(fetestexcept(FE_UNDERFLOW))
            printf("FE_UNDERFLOW");
    }

    puts("");
}

int main(void)
{
    errno = 0;
    feclearexcept(FE_ALL_EXCEPT);

    log(0.0);
    
    showErrno();
    showExceptions();

    return 0;
}


输出:

Error: ERANGE

Exceptions: FE_DIVBYZERO

注:使用Visual Studio编译。


相关内容:
MATH_ERRNO 表示通过errno报告错误的宏。
MATH_ERREXCEPT 表示通过引发浮点异常报告错误的宏。