michael
michael

Reputation: 85

C++ Best way to handle division by zero

I'm writing a C++ class that stores some double values in a vector (called mpValues) and calculates their average. When constructed, the value array is empty, so performing this calculation would return 0.0/0.0.

I decided that asking for the mean of zero values is a error. Therefore, it would be best to return NaN and display an error message, so that the user is made aware of that problem. The code looks like this:

double Average::CalculateAverage() const
{
    if(mpValues->size() == 0){
        std::cerr << "Instance of Average at: " << this << " contains no values.\n"
                  << "In this case the arithmetic mean is defined as NaN." <<std::endl;

        return 0.0/0.0;
    }
    else{
        ...calculate the arithmetic mean
    }
}

Is this a sensible approach, or do you have better suggestions? Usually, I wouldn't be so fussy, but this is a test for a job offer so I'd like to avoid bad decisions.

Thanks in advance!

Upvotes: 1

Views: 5492

Answers (5)

Walter
Walter

Reputation: 45414

this is a C++ question, so we should give a C++ answer. From the single-responsibility principle (mentioned by Don Reba), we conclude that reporting an error from within your function is not really appropriate. There are two main options.

1 specify clearly that calling your average(container) with an empty container is undefined behaviour (UB). This is standard practice with many algorithms in the C++ std library. It allows you to ignore the possibility of an empty container and just return sum/size(). You may add assert(size()>0); (or similar) in debug mode.

2 explicitly allow for empty containers in the API (which I think is what you wanted to). In this case, returning sum/size() is inappropriate. It may return NaN or trigger a signal, depending on the error settings, but even a NaN is not easy to catch (I think isnan() is not a standard library function). So you must somehow return the undefined result in a clean way. This can be done by throwing an appropriate exception or by returning a type, such as boost::optional<> (suggested by usta), which explicitly allows for an undefined value that is not an error (unlike NaN with double).

I consider throwing an exception as the most appropriate way in C++ (if you go for option 2).

Upvotes: 1

Tobias Langner
Tobias Langner

Reputation: 10808

You have 2 options - either return NaN or throw an exception. What you should do, depends on the usage.

1) the client displays the mean only: then I would choose to simply return NaN. This way, the client is not forced to write error handling code for something he doesn't bother.

2) the client calculates new values using the mean: then it is difficult. By throwing an exception, you force him to handle it explicitly. This can be a good thing. On the other hand - the double value NaN can be used in calculations as far as I know. It also depends on the rest of your work. If you always use exceptions, you should use one as well. If you always use error codes, you should use NaN. If you mix - you should clean that up.

P.S.: I wouldn't write 0.0/0.0 but use std::numeric_limits instead. It's easier to read.

Upvotes: -1

Don Reba
Don Reba

Reputation: 14031

The standard options are to return NaN, throw an exception, or return an option, such as boost::optional. There are advantages and disadvantages to each, which have been reviewed in detail by numerous people. Just do not display error messages within the function, since this violates the single responsibility principle.

Upvotes: 7

Zaur Nasibov
Zaur Nasibov

Reputation: 22659

You've already answered the question:

I decided that asking for the mean of zero values is an error.

Thus, there is no need to return NaN or handle zero division. You can create your own exception class (e.g. EmptyVectorError) and throw and catch it.

Upvotes: 3

usta
usta

Reputation: 6869

Change the return type to boost::optional<double>, I'd suggest.

Link to Doc

Upvotes: 0

Related Questions