Я пишу класс 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
}
}
Это разумный подход, или у вас есть лучшие предложения? Обычно я не был бы таким суетливым, но это тест на предложение о работе, поэтому я хотел бы избежать неправильных решений.
Заранее спасибо!
Стандартные опции — возвращать NaN, генерировать исключение или возвращать опцию, такую как boost :: option. У каждого есть свои преимущества и недостатки, которые были подробно рассмотрены многими людьми. Только не отображайте сообщения об ошибках внутри функции, так как это нарушает принцип единой ответственности.
Вы уже ответили на вопрос:
Я решил, что запрос среднего значения является ошибкой.
Таким образом, нет необходимости возвращать NaN или обрабатывать деление на ноль. Вы можете создать свой собственный класс исключений (например, EmptyVectorError) и бросить и поймать его.
это вопрос 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).
Измените тип возврата на boost::optional<double>
Я бы предложил.
У вас есть 2 варианта — либо вернуть NaN, либо выдать исключение. Что вы должны сделать, зависит от использования.
1) клиент отображает только среднее значение: тогда я бы просто решил вернуть NaN. Таким образом, клиент не вынужден писать код обработки ошибок для чего-то, что его не беспокоит.
2) клиент вычисляет новые значения, используя среднее значение: тогда это сложно. Вызывая исключение, вы заставляете его обращаться с ним явно. Это может быть хорошо. С другой стороны — насколько я знаю, в расчетах можно использовать двойное значение NaN. Это также зависит от остальной части вашей работы. Если вы всегда используете исключения, вы должны использовать и их. Если вы всегда используете коды ошибок, вы должны использовать NaN. Если вы смешиваете — вы должны очистить это.
П.С .: Я бы не писал 0.0 / 0.0, но использовал бы СТД :: numeric_limits вместо. Это легче читать.