6

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

我有两个问题:

  1. 考虑这些情况的最佳方法是什么?
  2. 非规范化数字机器的值是否依赖?
4

3 回答 3

10
#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之间),如果大小变化很大(10 6的因子就可以),上述情况也是有问题的。如果是这种情况,您需要更复杂的斜边函数。
于 2011-07-18T13:23:29.443 回答
10

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) {
    // ...
}
于 2011-07-18T13:37:55.393 回答
-1

您可以在求和时使用标志来确保并非每个元素都等于 0。

于 2011-07-18T13:25:38.727 回答