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

Check for zero or a denormalized number in c++

本文关键字:非规范 规范化 数字 c++ 检查      更新时间:2023-10-16

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

我有两个问题:
  1. 考虑这些情况的最好方法是什么?
  2. 非规格化数的值是否依赖于机器?

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) {
    // ...
}
#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和10154之间),如果震级变化很大(106就可以了),上述问题也是有问题的。如果是这种情况,你需要一个更复杂的斜边函数。

可以在求和时使用标记,以确保不是每个元素都等于0。