MATHERR - Linux手册页

时间:2019-08-20 18:00:51  来源:igfitidea点击:

Linux程序员手册 第3部分
更新日期: 2020-06-09

名称

matherr-SVID数学库异常处理

语法

#include <math.h>

int matherr(struct exception *exc);

extern _LIB_VERSION_TYPE _LIB_VERSION;

与-lm链接。

说明

注意:glibc不再支持此页面中描述的机制。在glibc 2.27之前,它已被标记为过时。从glibc 2.27开始,该机制已完全删除。新应用程序应使用math_error(7)和fenv(3)中描述的技术。此页面记录了matherr()机制,以帮助维护和移植较旧的应用程序。

系统V接口定义(SVID)指定如果检测到数学异常,则各种数学函数应调用一个名为matherr()的函数。在数学函数返回之前,将调用此函数;在matherr()返回之后,系统然后返回到math函数,后者又返回到调用者。

要使用matherr(),程序员必须定义_SVID_SOURCE功能测试宏(在包含任何头文件之前),并将值_SVID_分配给外部变量_LIB_VERSION。

系统提供默认版本的matherr()。此版本不执行任何操作,并返回零(有关其重要性,请参见下文)。可以由程序员定义的版本覆盖默认的matherr(),当发生异常时将调用该版本。该函数使用一个参数(指向异常结构的指针)调用,该参数的定义如下:

struct exception {
    int    type;      /* Exception type */
    char  *name;      /* Name of function causing exception */
    double arg1;      /* 1st argument to function */
    double arg2;      /* 2nd argument to function */
    double retval;    /* Function return value */
}

类型字段具有以下值之一:

DOMAIN
发生域错误(函数参数超出了定义函数的范围)。返回值取决于函数。 errno设置为EDOM。
SING
发生极点错误(函数结果为无穷大)。在大多数情况下,返回值是HUGE(最大的单精度浮点数),并带有适当的符号。在大多数情况下,errno设置为EDOM。
OVERFLOW
发生溢出。在大多数情况下,将返回值HUGE,并将errno设置为ERANGE。
UNDERFLOW
发生下溢。返回0.0,并将errno设置为ERANGE。
TLOSS
完全失去意义。返回0.0,并将errno设置为ERANGE。
PLOSS
部分失去意义。在glibc(和许多其他系统)上未使用此值。

arg1和arg2字段是提供给函数的参数(对于仅接受一个参数的函数,arg2是未定义的)。

retval字段指定数学函数将返回给其调用方的返回值。程序员定义的matherr()可以修改此字段以更改math函数的返回值。

如果matherr()函数返回零,则系统如上所述设置errno,并可能在标准错误上显示错误消息(请参见下文)。

如果matherr()函数返回非零值,则系统不会设置errno,也不会显示错误消息。

Math functions that employ matherr()

下表列出了调用matherr()的函数和环境。 "类型"列表示调用matherr()时分配给exc-> type的值。 "结果"列是分配给exc-> retval的默认返回值。

"消息"? " errno"和" errno"列描述了matherr()返回零时的默认行为。如果是"留言"?列包含" y",然后系统在标准错误上显示错误消息。

该表使用以下符号和缩写:

x        first argument to function
y        second argument to function
fin      finite value for argument
neg      negative value for argument
int      integral value for argument
o/f      result overflowed
u/f      result underflowed
|x|      absolute value of x
X_TLOSS  is a constant defined in <math.h>
|||||| |--- |--- |--- |--- |--- | |Function|Type|Result|Msg?|errno| |acos(|x|>1)|DOMAIN|HUGE|y|EDOM| |asin(|x|>1)|DOMAIN|HUGE|y|EDOM| |atan2(0,0)|DOMAIN|HUGE|y|EDOM| |acosh(x<1)|DOMAIN|NAN|y|EDOM| | | |-HUGE_VAL||| |cosh(fin) o/f|OVERFLOW|HUGE|n|ERANGE| |sinh(fin) o/f|OVERFLOW|(x>0.0) ?|n|ERANGE| | | |HUGE : -HUGE||| |sqrt(x<0)|DOMAIN|0.0|y|EDOM| |hypot(fin,fin) o/f|OVERFLOW|HUGE|n|ERANGE| |exp(fin) o/f|OVERFLOW|HUGE|n|ERANGE| |exp(fin) u/f|UNDERFLOW|0.0|n|ERANGE| |exp2(fin) o/f|OVERFLOW|HUGE|n|ERANGE| |exp2(fin) u/f|UNDERFLOW|0.0|n|ERANGE| |exp10(fin) o/f|OVERFLOW|HUGE|n|ERANGE| |exp10(fin) u/f|UNDERFLOW|0.0|n|ERANGE| |j0(|x|>X_TLOSS)|TLOSS|0.0|y|ERANGE| |j1(|x|>X_TLOSS)|TLOSS|0.0|y|ERANGE| |jn(|x|>X_TLOSS)|TLOSS|0.0|y|ERANGE| |y0(x>X_TLOSS)|TLOSS|0.0|y|ERANGE| |y1(x>X_TLOSS)|TLOSS|0.0|y|ERANGE| |yn(x>X_TLOSS)|TLOSS|0.0|y|ERANGE| |y0(0)|DOMAIN|-HUGE|y|EDOM| |y0(x<0)|DOMAIN|-HUGE|y|EDOM| |y1(0)|DOMAIN|-HUGE|y|EDOM| |y1(x<0)|DOMAIN|-HUGE|y|EDOM| |yn(n,0)|DOMAIN|-HUGE|y|EDOM| |yn(x<0)|DOMAIN|-HUGE|y|EDOM| |lgamma(fin) o/f|OVERFLOW|HUGE|n|ERANGE| |lgamma(-int) or|SING|HUGE|y|EDOM| | lgamma(0)||||| |tgamma(fin) o/f|OVERFLOW|HUGE_VAL|n|ERANGE| |tgamma(-int)|SING|NAN|y|EDOM| |tgamma(0)|SING|copysign(|y|ERANGE| | | |HUGE_VAL,x)||| |log(0)|SING|-HUGE|y|EDOM| |log(x<0)|DOMAIN|-HUGE|y|EDOM| |log2(0)|SING|-HUGE|n|EDOM| |log10(x<0)|DOMAIN|-HUGE|y|EDOM| |pow(0.0,0.0)|DOMAIN|0.0|y|EDOM| |pow(x,y) o/f|OVERFLOW|HUGE|n|ERANGE| |pow(x,y) u/f|UNDERFLOW|0.0|n|ERANGE| |pow(NaN,0.0)|DOMAIN|x|n|EDOM| |0**neg|DOMAIN|0.0|y|EDOM| |scalb() o/f|OVERFLOW|(x>0.0) ?|n|ERANGE| | | |HUGE_VAL :||| | | |-HUGE_VAL||| |scalb() u/f|UNDERFLOW|copysign(|n|ERANGE| | | | 0.0,x)||| |fmod(x,0)|DOMAIN|x|y|EDOM| |remainder(x,0)|DOMAIN|NAN|y|EDOM| |For an explanation of the terms used in this section, see||||| |allbox;||||| |lb lb lb||||| |l l l.||||| |Interface|Attribute|Value||| |matherr()|Thread safety|MT-Safe|||

示例

该示例程序演示了在调用log(3)时使用matherr()的方法。该程序最多包含三个命令行参数。第一个参数是要赋予log(3)的浮点数。如果提供了可选的第二个参数,则将_LIB_VERSION设置为SVID,以便调用matherr(),并将命令行参数中提供的整数用作matherr()的返回值。如果提供了可选的第三个命令行参数,则它指定了matherr()应该分配为数学函数的返回值的替代返回值。

以下示例运行不使用matherr(),其中log(3)的参数设置为0.0,

$ ./a.out 0.0
errno: Numerical result out of range
x=-inf

在以下运行中,将调用matherr()并返回0:

$ ./a.out 0.0 0
matherr SING exception in log() function
        args:   0.000000, 0.000000
        retval: -340282346638528859811704183484516925440.000000
log: SING error
errno: Numerical argument out of domain
x=-340282346638528859811704183484516925440.000000

消息"日志:SING错误"由C库打印。

在以下运行中,调用matherr()并返回非零值:

$ ./a.out 0.0 1
matherr SING exception in log() function
        args:   0.000000, 0.000000
        retval: -340282346638528859811704183484516925440.000000
x=-340282346638528859811704183484516925440.000000

在这种情况下,C库未打印消息,并且未设置errno。

在以下运行中,将调用matherr(),更改math函数的返回值,并返回非零值:

$ ./a.out 0.0 1 12345.0
matherr SING exception in log() function
        args:   0.000000, 0.000000
        retval: -340282346638528859811704183484516925440.000000
x=12345.000000

Program source

#define _SVID_SOURCE
#include <errno.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

static int matherr_ret = 0;     /* Value that matherr()
                                   should return */
static int change_retval = 0;   /* Should matherr() change
                                   functionaqs return value? */
static double new_retval;       /* New function return value */

int
matherr(struct exception *exc)
{
    fprintf(stderr, "matherr %s exception in %s() function\n",
           (exc->type == DOMAIN) ?    "DOMAIN" :
           (exc->type == OVERFLOW) ?  "OVERFLOW" :
           (exc->type == UNDERFLOW) ? "UNDERFLOW" :
           (exc->type == SING) ?      "SING" :
           (exc->type == TLOSS) ?     "TLOSS" :
           (exc->type == PLOSS) ?     "PLOSS" : "???",
            exc->name);
    fprintf(stderr, "        args:   %f, %f\n",
            exc->arg1, exc->arg2);
    fprintf(stderr, "        retval: %f\n", exc->retval);

    if (change_retval)
        exc->retval = new_retval;

    return matherr_ret;
}

int
main(int argc, char *argv[])
{
    double x;

    if (argc < 2) {
        fprintf(stderr, "Usage: %s <argval>"
                " [<matherr-ret> [<new-func-retval>]]\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if (argc > 2) {
        _LIB_VERSION = _SVID_;
        matherr_ret = atoi(argv[2]);
    }

    if (argc > 3) {
        change_retval = 1;
        new_retval = atof(argv[3]);
    }

    x = log(atof(argv[1]));
    if (errno != 0)
        perror("errno");

    printf("x=%f\n", x);
    exit(EXIT_SUCCESS);
}

另外参见

fenv(3),math_error(7),standards(7)

出版信息

这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/