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

MATH_ERREXCEPT宏


概要:
#include <math.h>
#define MATH_ERREXCEPT 2

描述:

该宏会扩展为整型常量2,用于测试宏math_errhandling值,以确定数学函数是否通过引发浮点异常报告错误。


除非另有明确说明,否则<math.h>头文件中的每个函数对输入实参的所有可表示值都进行了规定。每个函数的执行像单一操作一样,且不会引发SIGFPE信号,也不会产生FE_INVALID、FE_DIVBYZERO或者FE_OVERFLOW等浮点异常,除非是为了反映函数结果。

ISO/IEC 9899:2024标准第7.12.2 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):普通精度的情况下,非0结果值的绝对值小于结果类型的最小规格化数(minimum normalized number),这时会发生下溢,例如: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):普通精度的情况下,非0结果值的绝对值小于结果类型的最小规格化数(minimum normalized number),这时会发生下溢,例如: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)值等于0,errno应设置为与错误对应的值或者保持不变。如果没有发生上述错误,无论math_errhandling如何设置,errno都应保持不变。根据ISO/IEC 9899标准,数学错误应通过浮点异常标志来指示,而不是通过errno。

⑥ 每个库函数都会列出所有必须报告的定义域错误;实现可以定义额外的定义域错误,前提是这些错误与函数的数学定义一致,例如:在支持无穷大的实现中,如果函数的数学定义域不包含无穷大,则允许将无穷大参数视为定义域错误。信号非数值输入是否视为定义域错误将由实现定义。

⑦ 每个库函数都会列出所有必须报告的极点错误;实现可以定义额外的极点错误,前提是这些错误与函数的数学定义一致。发生极点错误时,函数返回实现定义值。

⑧ 当结果出现上溢或者下溢时,会发生范围错误。每个库函数都会列出所有必须报告的范围错误;实现可以定义额外的范围错误,前提是这些错误与函数的数学定义一致,并且是由上溢或者下溢导致。必须报告的范围错误应按ISO/IEC 9899标准规定报告;实现定义的范围错误可以按ISO/IEC 9899标准规定选择是否报告。

⑨ 结果为确切无穷大的情况不属于上溢。如果浮点运算结果上溢并且采用默认舍入方式,函数将根据返回类型返回宏HUGE_VAL、HUGE_VALF或者HUGE_VALL,其符号与函数正确结果值相同;对于超出上溢阈值后采用降低精度表示的数值类型,函数可能返回该类型的精度低于完整精度的结果表示。

⑩ 规定为0值的0结果不属于下溢。普通精度下结果为最小规格化数也可能发生下溢。如果发生下溢,函数返回实现定义值,其绝对值不大于指定类型的最小正规格化数。这里的下溢包括ISO/IEC 60559标准中的逐级下溢(gradual underflow)和刷0下溢(flush-to-zero underflow)。


范例:
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 
/*宏MATH_ERREXCEPT范例*/

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

int main(void)
{
    feclearexcept(FE_ALL_EXCEPT);
    double x = log(0.0);

    if(math_errhandling & MATH_ERREXCEPT)
    {
        printf("Floating-point exception: ");
        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("");
    }
    else
        puts("No floating-point status flag is set.");

    return 0;
}


输出:

Floating-point exception: FE_DIVBYZERO


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


主要参考资料:

1、ISO/IEC 9899:2024

2、ISO/IEC 9899:2018