2011-08-08 46 views
9

我有一些数学(在C++中),其中似乎将生成一些非常小的,接近零的数字(我怀疑trig函数调用是我真正的问题),但我想检测这些情况,以便我可以更详细地研究它们。如何检查和处理非常接近零的数字

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

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

二,数学的本质是三角函数的性质(又名采用了很多弧度/度的转换和sin/cos/tan电话等),我可以做什么样的变革,以避免数学错误?

很显然,乘法运算可以使用log transform - 还有什么?

+0

我们可以请看一个上述数学的例子,以便我们可以设计一些优雅的东西?当我可以在零点附近缓慢地改变结果时,我脑海中的东西就像'cos x - 1',必须仔细选择容差。 –

+1

至于避免下溢的转换,最直接的就是泰勒扩展你的表达式,并使用小的参数。例如,而不是'1-cos(x)'使用'x * x/2'来表示'x'小于某个临界值。 –

回答

2

如果x是一个双,那么一个问题,这种方法是,你不能x区分是合法零,x是正值比DBL_MIN小。所以如果你知道x永远不可能是合法的零,并且你想知道什么时候发生了下溢,这将会起作用。

您还可以尝试捕获SIGFPE信号,该信号在任何时候出现数学错误(包括浮点下溢)时将在POSIX兼容系统上触发。请参阅:http://en.wikipedia.org/wiki/SIGFPE

编辑:很明显,DBL_MIN是不是最大的负值,一个双能装,它是最小正normalized值双能容纳。所以只要价值不能为零,你的方法就没有问题。

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

2

由于您使用的是C++,最常用的方法是使用标头<limits>中的std::numeric_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_MIN,等于<cfloat>)的最小的正非非标准化值,第二个是类型为T(不等于<cfloat>)的最小正值。

[您可能会发现this document有用的信息,如果你不放心浮点数的表示。]

+0

可能在今天晚些时候,我弄清楚了哪些部分的问题导致了问题。感谢C++珍闻! – Petriborg

+0

'DBL_MIN'是最小的正数**正规化的**'double'值,所以它将对应于'min()'而不是'denorm_min()'。 –

+0

@DanielFischer:的确,谢谢。纠正。 –

0

第一if检查时你的价值为零将仅实际上是真实的。

关于第二个问题,你意味着大量的转换。相反,选择一个单位(deg或rad)并在该单位中执行所有计算操作。然后在最后做一个单一的转换到另一个值,如果你需要。

+0

'DBL_MIN'是最小的正**正规化**双倍值,有更小的正双倍。 –

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是否为规格化(也称为低于正常)号码或±0.0。不知道更多关于你的具体情况,我不知道这个测试是否合适。非规格化的数字可以是合理的计算结果,也可以是正确结果为0的四舍五入的结果。当数学上正确的结果为0时,四舍五入也可能产生远大于DBL_MIN的数量,因此可能有一个更大的阈值是明智的。

+0

感谢您对此提出的意见 - 问题仍在继续,但我没有时间去实际回去处理。我可能会尝试发布一个更聪明的问题。 – Petriborg