阅读:0
作者:严长生
域错误(domain error)
在 <math.h> 头文件中,某些函数仅针对一定范围内的数值有意义,我们称这个范围为域(domain)。例如,sqrt() 函数仅能对非负数求平方根,所以此函数的域就为非负数。
如果我们给这类函数传递一个在域范围之外的参数,函数就会产生错误,我们称这种错误为域错误(domain error)。
C99 标准新增加了 6 个头文件,其中的 <fenv.h> 专门用来处理浮点数错误,域错误也可以借助其中的 fetestexcept() 函数和 FE_INVALID 宏检测出来。
有些编译器采用了较新的 C99 标准,不再设置 errno 的值了,例如 Mac OS 下的 Xcode。
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
如果我们给这类函数传递一个在域范围之外的参数,函数就会产生错误,我们称这种错误为域错误(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