返回NaN还是抛出异常?

时间:2011-09-03 13:21:12

标签: c++ statistics numeric nan

我有一个函数可以获取一个样本(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 个答案:

答案 0 :(得分:4)

我认为NaN在数学上会更正确。最后它是0.0/0。如果它是一个直接的分裂,会发生什么?

请注意,关于C ++和例外,存在神圣的战争。例如,请阅读:To throw or not to throw exceptions?

答案 1 :(得分:2)

我会将行为保留为未定义。

只需为非空案例编写代码,让调用者考虑正确使用它。可能你不会为空矢量调用它,因为空输入的检查可能会提前完成。

答案 2 :(得分:1)

您对使用例外的理解是正确的,您应该采用这种方法。例外是为了这个目的(throw当出现异常情况时)。

在这种情况下,假设您返回NaN,那么每当您调用函数average()时,您必须确保这一点,您需要额外检查一下{{1}情景。

[注意:最重要的是,确保条件NaN不是经常发生的情况。 IMO,如果频繁抛出,我不会使用例外。]

答案 3 :(得分:1)

我会抛出,只是为了保持安全,并确保立即检测到错误,而不是如你所说,过了一会儿。

实际上在这个特定的用例中你可以返回0,如果有意义的话说0是“无”的平均值。

我们通常做的是在我们进入方法后立即验证参数,如果我们抛出ArgumentNullException或OutOfRangeException,如果该方法实际上只是用非null和正确填充的参数调用。