检查c ++中的零或非规范化数字

时间:2011-07-18 13:17:20

标签: c++ divide-by-zero

我目前有一些代码,我必须规范化双精度矢量(将每个元素除以总和)。在调试时,我有时会看到向量中的元素都是0.0。如果我然后得到元素的总和,我得到0.0或4.322644347104e-314 #DEN(我最近发现的是非规范化数字)。当sum为0.0或非规格化数时,我想阻止对情形进行归一化。我能想到处理这两种情况的唯一方法是检查总和是否小于'epsilon',其中epsilon是一个小数字(但我不确定制作epsilon有多小)。

我有两个问题:

  1. 考虑这些案例的最佳方法是什么?
  2. 非规范化号码机的值是否依赖?

3 个答案:

答案 0 :(得分:9)

#include <limits>
#include <cmath>
double epsilon = std::numeric_limits<double>::min();
if (std::abs(sum) < epsilon) {
  // Don't divide by sum.
}
else {
  // Scale vector components by sum.
}

<强>附录
既然你试图规范化一个向量,我会冒险你的总和是向量元素的平方和,概念上

double sum = 0;
for (unsigned int ii = 0; ii < vector_size; ++ii) {
    sum += vector[ii]*vector[ii];
}
sum = std::sqrt(sum);

上述问题有三个。

  1. 如果这些矢量成分中的任何一个在幅度上大于sqrt(max_double),那么你将获得无穷大。
  2. 如果这些矢量组件中的任何一个在幅度上小于sqrt(min_double),则会出现下溢。
  3. 即使数字表现良好(幅度在2 * 10 -154 和10 154 之间),如果幅度变化很大,上述情况也会出现问题(a因子10 6 会这样做。如果是这种情况,你需要一个更复杂的斜边函数。

答案 1 :(得分:8)

C99提供fpclassify来检测非规范化数字。它还提供了C ++ 0x和Boost.Math。

// C++0x
#include <cmath>
using std::fpclassify;

// Boost
//#include <boost/math/special_functions/fpclassify.hpp>
//using boost::math::fpclassify;

if(fpclassify(sum) == FP_SUBNORMAL) {
    // ...
}

答案 2 :(得分:0)

您可以在获取总和时使用标记,以确保不是每个元素都等于0.