MATH_ERRNO, MATH_ERREXCEPT, math_errhandling
描述
宏常量 math_errhandling
扩展为一个 int
类型的表达式,该表达式等于 MATH_ERRNO
,或等于 MATH_ERREXCEPT
,或等于它们的位或 (MATH_ERRNO
| MATH_ERREXCEPT
)。
math_errhandling
的值表示浮点运算符和函数执行的错误处理类型
常量解释 MATH_ERREXCEPT
表示使用浮点异常:在 <cfenv>
中至少定义了 FE_DIVBYZERO
、FE_INVALID
和 FE_OVERFLOW
。 MATH_ERRNO
表示浮点操作使用变量 errno
报告错误。
如果实现支持 IEEE 浮点算术 (IEC 60559),则 math_errhandling
& MATH_ERREXCEPT
必须是非零。
识别以下浮点错误条件
条件 | 解释 | errno | 浮点异常 | 示例 |
---|---|---|---|---|
域错误 | 参数超出操作在数学上定义的范围(每个函数的描述列出了所需的域错误) | EDOM | FE_INVALID | std::acos(2) |
极点错误 | 函数的数学结果正好是无限或未定义的 | ERANGE | FE_DIVBYZERO | std::log(0.0), 1.0/0.0 |
由于溢出的范围错误 | 数学结果是有限的,但舍入后变为无限,或向下舍入后变为可表示的最大有限值 | ERANGE | FE_OVERFLOW | std::pow(DBL_MAX,2) |
由于下溢的范围错误 | 结果非零,但舍入后变为零,或变为次正规数并损失精度 | ERANGE 或不变(实现定义) | FE_UNDERFLOW 或无(实现定义) | DBL_TRUE_MIN/2 |
不精确结果 | 结果必须舍入以适应目标类型 | 不变 | FE_INEXACT 或无(未指定) | std::sqrt(2), 1.0/10.0 |
声明
#define MATH_ERRNO
#define MATH_ERREXCEPT
#define math_errhandling /*implementation defined*/
备注
数学库函数是否引发 FE_INEXACT
通常未指定,但可以在函数描述中明确指定(例如 std::rint
与 std::nearbyint
)
在 C++11 之前,未指定浮点异常,任何域错误都需要 EDOM
,溢出需要 ERANGE
,下溢则由实现定义。
示例
#include <iostream>
#include <cfenv>
#include <cmath>
#include <cerrno>
#include <cstring>
#pragma STDC FENV_ACCESS ON
int main()
{
std::cout
<< "MATH_ERRNO is "
<< (math_errhandling & MATH_ERRNO ? "set" : "not set") << '\n'
<< "MATH_ERREXCEPT is "
<< (math_errhandling & MATH_ERREXCEPT ? "set" : "not set") << '\n';
std::feclearexcept(FE_ALL_EXCEPT);
errno = 0;
std::cout
<< "log(0) = "
<< std::log(0) << '\n';
if(errno == ERANGE)
std::cout
<< "errno = ERANGE ("
<< std::strerror(errno) << ")\n";
if(std::fetestexcept(FE_DIVBYZERO))
std::cout
<< "FE_DIVBYZERO (pole error) reported\n";
}
MATH_ERRNO is set
MATH_ERREXCEPT is set
log(0) = -inf
errno = ERANGE (Numerical result out of range)
FE_DIVBYZERO (pole error) reported