Проверьте ноль или денормализованное число в c ++ - PullRequest
5 голосов
/ 18 июля 2011

В настоящее время у меня есть некоторый код, где я должен нормализовать вектор двойных чисел (разделить каждый элемент на сумму).При отладке я иногда вижу, что все элементы вектора равны 0.0.Если я тогда возьму сумму элементов, я получу либо 0.0, либо 4.322644347104e-314 # DEN (недавно выяснилось, что это денормализованное число).Я хотел бы предотвратить нормализацию вектора для случаев, когда сумма равна либо 0,0, либо денормализованному числу.Единственный способ, которым я мог бы подумать об обработке этих двух случаев, - это проверить, меньше ли сумма, чем «эпсилон», где эпсилон - это небольшое число (но я не уверен, насколько мал, чтобы сделать эпсилон).У меня есть 2 вопроса:

  1. Каков наилучший способ учета этих случаев?
  2. Зависит ли значение денормализованного числового автомата?

Ответы [ 3 ]

9 голосов
/ 18 июля 2011
#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 ).Вам нужна более сложная функция гипотенузы, если это так.
8 голосов
/ 18 июля 2011

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) {
    // ...
}
0 голосов
/ 18 июля 2011

Вы можете использовать флаг, пока берете сумму, чтобы убедиться, что не каждый элемент равен 0.

...