10

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

我目前正在尝试以下方法,是否正确?

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

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

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

4

4 回答 4

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);
}

可能会有肯定的回答。该条件检查是否x是非规范化(也称为subnormal)数或 ±0.0。在不了解您的具体情况的情况下,我无法判断该测试是否合适。非规范化的数字可以是计算的合法结果,也可以是舍入的结果,其中正确的结果为 0。舍入产生的数字也可能比DBL_MIN数学上正确的结果为 0 时的数量级大得多,因此可以使用更大的阈值明智的。

于 2012-02-17T22:15:44.070 回答
2

由于您使用的是 C++,因此最惯用的方法是使用std::numeric_limitsfrom header <limits>

例如:

template <typename T>
bool is_close_to_zero(T x)
{
    return std::abs(x) < std::numeric_limits<T>::epsilon();
}

要使用的实际容差很大程度上取决于您的问题。请用一个具体的用例完成您的问题,以便我可以增强我的答案。

还有std::numeric_limits<T>::min()std::numeric_limits<T>::denorm_min()这可能是有用的。第一个是类型的最小正非规范化值T(等于FLT/DBL/LDBL_MINfrom <cfloat>),第二个是类型的最小正值T(不<cfloat>等价)。

[如果您对浮点数表示不满意,您可能会发现阅读此文档很有用。]

于 2011-08-08T13:12:22.047 回答
2

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

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

编辑:要清楚,DBL_MIN不是双精度可以容纳的最大负值,它是双精度可以容纳的最小正归一化值。因此,只要值不能为零,您的方法就可以了。

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

于 2011-08-08T12:48:23.650 回答
0

第一次if检查实际上只有在您的值为零时才为真。

对于第二个问题,您暗示了很多转换。相反,选择一个单位(度或弧度)并在该单位中进行所有计算操作。然后,如果需要,最后进行一次转换为另一个值。

于 2011-08-08T13:31:19.253 回答