阅读:0       作者:严长生

域错误(domain error)

在 <math.h> 头文件中,某些函数仅针对一定范围内的数值有意义,我们称这个范围为域(domain)。例如,sqrt() 函数仅能对非负数求平方根,所以此函数的域就为非负数。

如果我们给这类函数传递一个在域范围之外的参数,函数就会产生错误,我们称这种错误为域错误(domain error)

检测域错误信息

在 C99 标准之前,域错误的信息只能通过 <errno.h> 中的 errno 获取。当发生域错误时,程序会将 errno 的值由默认的 0 改为 EDOM。

C99 标准新增加了 6 个头文件,其中的 <fenv.h> 专门用来处理浮点数错误,域错误也可以借助其中的 fetestexcept() 函数和 FE_INVALID 宏检测出来。

有些编译器采用了较新的 C99 标准,不再设置 errno 的值了,例如 Mac OS 下的 Xcode。

NaN(Not a Number)

当发生域错误时,某些返回值类型为浮点数的函数会将返回值设置为 NaN(Not a Number),表示这是一个“无效的数字”。还是以 sqrt() 为例,sqrt(-100) 的返回值就是 NaN。想进一步了解 NaN,请猛击《NaN(Not a Number),表示一个无效数字》。

实例

用代码来演示域错误:
#include <stdio.h> /* printf */
#include <math.h> /* sqrt */
#include <errno.h> /* errno */
#include <fenv.h> /* FE_INVALID */
int main()
{
    printf("sqrt(-100) = %f\n", sqrt(-100));
    if (errno == EDOM) {
        perror("errno == EDOM");
    }
    if (fetestexcept(FE_INVALID)) {
        puts("FE_INVALID is set");
    }
    return 0;
}
在 VS2015 下的运行结果:
sqrt(-100) = -nan(ind)
errno == EDOM: Domain error
FE_INVALID is set

在 GCC 下的运行结果:
sqrt(-100) = -nan
errno == EDOM: Numerical argument out of domain
FE_INVALID is set

在 Xcode 下的运行结果:
sqrt(-100) = nan
FE_INVALID is set