开发者

Returning NaN or throwing an exception?

开发者 https://www.devze.com 2023-04-02 20:31 出处:网络
I have a function that gets a sample (an std::vector<double>) as input and computes the average of the sample: what is the best way to handle the empty input vector case?

I have a function that gets a sample (an std::vector<double>) as input and computes the average of the sample: what is the best way to handle the empty input vector case?

My first idea is to throw an exception like in this snippet:

double average(const std::vector<doubl开发者_运维知识库e>& 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;
}

But I think another solution could be to return 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;
}

I like the exception because it shows where the problem happened while if I get a NaN in a final result of a long computation I will have more difficulties to understand where the NaN was born. Anyway with the NaN I like the possibility of returning a "special" double to signal something unexpected happened.

Is there any other way of cope with the empty vector? Thank you.


I DO think that mathematically the NaN would be more correct. In the end it's 0.0/0. Had it been a direct division, what would have happened?

Be aware that about C++ and exceptions there are holy wars. For example read this: To throw or not to throw exceptions?


I would leave the behavior undefined.

Just code it for the non-empty case and let the caller think about using it correctly. Probably you won't call it for empty vectors anyway as the check for the empty input will probably be done earlier.


Your understanding for using exceptions is correct and you should go ahead with that approach. Exceptions are meant for this purpose (throw when exceptional condition happens).

In this case, suppose if you return NaN, then every time you call the function average() you have to make sure that, you are putting an extra check which takes care of NaN scenario.

[Note: On top of that, make sure that the condition (sz == 0) is not a very frequently happening scenario. IMO, I won't use exceptions if they are thrown frequently.]


I would throw, just to keep on the safe side and make sure the error is detected immediately and not, as you said, after a while.

in fact in this specific use case you can return 0 if it make sense to say 0 is the average of "nothing".

what we do usually is to validate parameters as soon as we get inside the method and in case we throw ArgumentNullException or OutOfRangeException if really the method was designed to only be called with non null and properly filled arguments.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号