我正在编写一个C ++类,它在向量中存储一些double值(称为mpValues)并计算它们的平均值。构造时,value数组为空,因此执行此计算将返回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
}
}
这是一种明智的做法,还是你有更好的建议?通常,我不会那么挑剔,但这是对工作机会的考验,所以我想避免错误的决定。
提前致谢!
答案 0 :(得分:6)
标准选项是返回NaN,抛出异常或返回选项,例如boost :: optional。每种方法都有优点和缺点,许多人已对此进行了详细审查。只是不要在函数中显示错误消息,因为这违反了single responsibility principle。
答案 1 :(得分:3)
你已经回答了这个问题:
我决定要求零值的均值是一个错误。
因此,无需返回NaN或处理零分割。您可以创建自己的异常类(例如EmptyVectorError)并抛出并捕获它。
答案 2 :(得分:1)
这是一个C ++问题,所以我们应该给出一个C ++答案。根据单一责任原则(Don Reba提到),我们得出结论,从函数中报告错误并不合适。有两个主要选择。
1 明确指出,使用空容器调用average(container)
是未定义的行为(UB)。这是C ++ std
库中许多算法的标准做法。它允许您忽略空容器的可能性并返回sum/size()
。您可以在调试模式下添加assert(size()>0);
(或类似)。
2 明确允许API中的空容器(我认为这是你想要的)。在这种情况下,返回sum/size()
是不合适的。它可能会返回NaN
或触发信号,具体取决于错误设置,但即使NaN
也不容易捕获(我认为isnan()
不是标准库函数)。所以你必须以某种方式以一种干净的方式返回未定义的结果。这可以通过抛出适当的异常或返回类型来完成,例如boost::optional<>
(由usta建议),它明确允许未定义的值不是错误(与NaN
不同double
1}})。
我考虑将异常作为C ++中最合适的方式(如果你选择2)。
答案 3 :(得分:0)
我建议将返回类型更改为boost::optional<double>
。
答案 4 :(得分:-1)
您有2个选项 - 返回NaN或抛出异常。你应该做什么,取决于用途。
1)客户端仅显示均值:然后我会选择简单地返回NaN。这样,客户端就不会被迫为他不打扰的事情编写错误处理代码。
2)客户使用均值计算新值:然后很难。通过抛出异常,你强迫他明确地处理它。这可能是一件好事。另一方面 - 据我所知,双值NaN可用于计算。这还取决于你的其他工作。如果您总是使用例外,您也应该使用例外。如果您始终使用错误代码,则应使用NaN。如果你混合 - 你应该清理它。
P.S。:我不会写0.0 / 0.0而是使用std::numeric_limits代替。它更容易阅读。