6

現在、doubleのベクトルを正規化する必要があるコードがいくつかあります(各要素を合計で除算します)。デバッグ時に、ベクトル内の要素がすべて0.0であることが時々あります。次に要素の合計をとると、0.0または4.322644347104e-314#DENのいずれかが得られます(最近、非正規化数であることがわかりました)。合計が0.0または非正規化数の場合のベクトルの正規化を防ぎたいと思います。これらの2つのケースを処理することを考える唯一の方法は、合計が「イプシロン」よりも小さいかどうかを確認することです。ここで、イプシロンは少数です(ただし、イプシロンを作成するのにどれだけ小さいかはわかりません)。

2つの質問があります:

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

上記には3つの問題があります。

  1. これらのベクトル成分のいずれかがsqrt(max_double)、無限大になるよりも大きさが大きい場合。
  2. これらのベクトル成分のいずれかが、アンダーフローよりも大きさが小さい場合sqrt(min_double)
  3. 数値が適切に動作している場合でも(大きさが2 * 10-154から10154の間)、大きさが大きく異なる場合は上記の問題が発生します(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 に答える