C ++ Лучший способ справиться с делением на ноль

Я пишу класс C ++, который хранит некоторые двойные значения в векторе (называемые mpValues) и вычисляет их среднее значение. При построении массив значений пуст, поэтому выполнение этого вычисления вернет 0.0 / 0.0.

Я решил, что запрос среднего значения является ошибкой. Поэтому было бы лучше вернуть NaN и отобразить сообщение об ошибке, чтобы пользователь узнал об этой проблеме.
Код выглядит так:

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
}
}

Это разумный подход, или у вас есть лучшие предложения? Обычно я не был бы таким суетливым, но это тест на предложение о работе, поэтому я хотел бы избежать неправильных решений.

Заранее спасибо!

1

Решение

Стандартные опции — возвращать NaN, генерировать исключение или возвращать опцию, такую ​​как boost :: option. У каждого есть свои преимущества и недостатки, которые были подробно рассмотрены многими людьми. Только не отображайте сообщения об ошибках внутри функции, так как это нарушает принцип единой ответственности.

6

Другие решения

Вы уже ответили на вопрос:

Я решил, что запрос среднего значения является ошибкой.

Таким образом, нет необходимости возвращать NaN или обрабатывать деление на ноль. Вы можете создать свой собственный класс исключений (например, EmptyVectorError) и бросить и поймать его.

3

это вопрос C ++, поэтому мы должны дать ответ C ++. От принцип единоличной ответственности (упомянуто Доном Ребой), мы заключаем, что сообщение об ошибке изнутри вашей функции не совсем подходит. Есть два основных варианта.

1 четко указать, что зовет ваш average(container) с пустым контейнером неопределенное поведение (УБ). Это стандартная практика со многими алгоритмами в C ++ std библиотека. Это позволяет игнорировать возможность пустого контейнера и просто вернуть sum/size(), Вы можете добавить assert(size()>0); (или аналогичный) в режиме отладки.

2 явно разрешить пустые контейнеры в API (я думаю, это то, что вы хотели). В этом случае возвращение sum/size() неуместно Может вернуться NaN или вызвать сигнал, в зависимости от настроек ошибки, но даже NaN не легко поймать (я думаю isnan() не является стандартной библиотечной функцией). Таким образом, вы должны каким-то образом вернуть неопределенный результат чистым способом. Это можно сделать, выдав соответствующее исключение или вернув тип, такой как boost::optional<> (предложено usta), которое явно допускает неопределенное значение, которое не является ошибкой (в отличие от NaN с double).

Я считаю выбрасывание исключения наиболее подходящим способом в C ++ (если вы выберете вариант 2).

1

Измените тип возврата на boost::optional<double>Я бы предложил.

Ссылка на Док

0

У вас есть 2 варианта — либо вернуть NaN, либо выдать исключение. Что вы должны сделать, зависит от использования.

1) клиент отображает только среднее значение: тогда я бы просто решил вернуть NaN. Таким образом, клиент не вынужден писать код обработки ошибок для чего-то, что его не беспокоит.

2) клиент вычисляет новые значения, используя среднее значение: тогда это сложно. Вызывая исключение, вы заставляете его обращаться с ним явно. Это может быть хорошо. С другой стороны — насколько я знаю, в расчетах можно использовать двойное значение NaN. Это также зависит от остальной части вашей работы. Если вы всегда используете исключения, вы должны использовать и их. Если вы всегда используете коды ошибок, вы должны использовать NaN. Если вы смешиваете — вы должны очистить это.

П.С .: Я бы не писал 0.0 / 0.0, но использовал бы СТД :: numeric_limits вместо. Это легче читать.

-1
По вопросам рекламы [email protected]