如何检查和处理非常接近零的数字

Pet*_*org 10 c++ math numeric numerical-stability

我有一些数学(在C++中)似乎产生了一些非常小的,接近于零的数字(我怀疑trig函数调用是我真正的问题),但是我想检测这些情况以便我可以在更多详情.

我目前正在尝试以下内容,这是正确的吗?

if ( std::abs(x) < DBL_MIN ) {
     log_debug("detected small num, %Le, %Le", x, y);
}
Run Code Online (Sandbox Code Playgroud)

其次,数学的本质是三角函数(也就是使用很多弧度/度数转换和sin/ cos/ tan调用等),我可以做些什么样的转换来避免数学错误?

显然,对于乘法我可以使用对数变换 - 还有什么?

Dan*_*her 5

与普遍看法相反,DBL_MIN不是最小的正值double而是最小的正归一化 double值.通常 - 对于64位ieee754 doubles- 它是2 -1022,而最小的正值double是2 -1074.因此

我目前正在尝试以下内容,这是正确的吗?

if ( std::abs(x) < DBL_MIN ) {
     log_debug("detected small num, %Le, %Le", x, y);
}
Run Code Online (Sandbox Code Playgroud)

可能有一个肯定的答案.条件检查是否x是非规范化(也称为次正规)数或±0.0.如果不了解您的具体情况,我无法判断该测试是否合适.非规范化数字可以是合理的计算结果,也可以是正确结果为0的舍入结果.舍入产生的数量远大于DBL_MIN数学上正确的结果为0时的数量,因此更大的阈值可能是明智的.


Bis*_*ook 2

如果x是双精度数,那么这种方法的一个问题是您无法区分x合法的零和x小于 的正值DBL_MINx因此,如果您知道永远不可能合法地为零,并且您想查看何时发生下溢,那么这将起作用。

您还可以尝试捕获该SIGFPE信号,只要出现数学错误(包括浮点下溢),该信号就会在符合 POSIX 标准的系统上触发。请参阅: http: //en.wikipedia.org/wiki/SIGFPE

编辑:要明确的是,DBL_MIN不是双精度可以保存的最大负值,它是双精度可以保存的最小正标准化值。因此,只要该值不能为零,您的方法就可以。

另一个有用的常量是DBL_EPSILON可以与 1.0 相加而不会返回 1.0 的最小双精度值。请注意,这是一个比 更大的值DBL_MIN。但它可能对你有用,因为你正在做的三角函数可能趋向于 1 而不是趋向于 0。