Вернуть NaN или бросить исключение? - PullRequest
4 голосов
/ 03 сентября 2011

У меня есть функция, которая получает выборку (std::vector<double>) в качестве входных данных и вычисляет среднее значение выборки: каков наилучший способ обработки пустого входного вектора?

Моя первая идея заключается в том,бросить исключение, как в этом фрагменте кода:

double average(const std::vector<double>& sample)
{
   size_t sz = sample.size();
   if (sz==0) throw std::exception("unexpected empty vector");

   double acc = 0;
   for (size_t i=0; i<sz; ++i) acc += sample[i];
   return acc/sz;
}

Но я думаю, что другое решение может состоять в том, чтобы вернуть NaN:

double average(const std::vector<double>& sample)
{
   size_t sz = sample.size();
   if (sz==0) return std::numeric_limits<double>::quiet_NaN();

   double acc = 0;
   for (size_t i=0; i<sz; ++i) acc += sample[i];
   return acc/sz;
}

Мне нравится исключение, потому что оно показывает, где проблема возникла во времяесли я получу NaN в конечном результате длинных вычислений, у меня будет больше трудностей, чтобы понять, где родился NaN.В любом случае с NaN мне нравится возможность возвращать «специальный» дубль, чтобы сигнализировать о том, что произошло что-то неожиданное.

Есть ли другой способ справиться с пустым вектором?Спасибо.

Ответы [ 4 ]

4 голосов
/ 03 сентября 2011

Я действительно думаю, что математически NaN будет более правильным.В конце концов, это 0.0/0.Если бы это было прямое разделение, что бы произошло?

Помните, что в C ++ и исключениях есть священные войны.Например, прочитайте это: Бросать или не бросать исключения?

2 голосов
/ 03 сентября 2011

Я бы оставил поведение неопределенным.

Просто закодируйте его для непустого регистра и позвольте вызывающему абоненту подумать о его правильном использовании.Вероятно, вы все равно не будете вызывать его для пустых векторов, поскольку проверка пустого ввода, вероятно, будет выполнена раньше.

1 голос
/ 03 сентября 2011

Я бы бросил, просто чтобы быть в безопасности и убедиться, что ошибка обнаружена немедленно, а не, как вы сказали, через некоторое время.

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

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

1 голос
/ 03 сентября 2011

Ваше понимание использования исключений является правильным, и вы должны продолжать этот подход. Для этой цели предусмотрены исключения (throw при возникновении исключительного состояния).

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

[Примечание: Кроме того, убедитесь, что условие (sz == 0) не очень часто встречающийся сценарий. ИМО, я не буду использовать исключения, если их часто выдают.]

...