防止被零除的适当行为
Appropriate behaviour to prevent division by zero
我们被要求使用堆栈上的内存设计一个Vector3D类。我需要将向量除以标量,但是防止除以零的最合适行为是什么?我可以抛出一个例外吗?我不想返回 (0,0,0) 的 Vector3D,因为这表明操作成功,而实际上并非如此。
Vector3DStack Vector3DStack::operator / (float s) const
{
if (s == 0)
{
// How should I handle division by zero?
// Method is expecting a Vector3DStack to be returned.
}
return Vector3DStack(x / s, y / s, z / s);
}
抛出一个std::invalid_argument
,它派生自一个std::logic_error
;它通过一个无效的参数表明程序的逻辑流有问题。
这实际上取决于Vector3DStack的用途。
你可以
- 引发异常
- 使其可配置(也许检查仅在调试模式下发生)
- 只需允许div 由零返回 Nan - 调用者可以使用 std::isnan() 进行检查
- 指定问题。写下调用方的责任,它不将 s 设置为 0(这称为前提条件)
哪个最好取决于。
你绝对应该抛出一个异常。这就是例外的用途 - 在您的代码中指示特殊情况。实际上,您也可以允许在零附近设置较小的容差,例如:
Vector3DStack Vector3DStack::operator / (float s) const
{
if (fabs(s) < 1e-10) {
... throw some exception to indicate you are dividing a vector by zero.
}
return Vector3DStack(x / s, y / s, z / s);
}
由于您必须从运算符返回一个值,因此您有两个选择:
- 抛出异常(绝对首选)
- 返回一个由三个
NaN
组成的向量。
顺便说一下,你不应该怀疑浮点值是否等于零,因为你会得到很多假阴性。由于特定的浮点运算,您应该将除数与非常小的值进行比较(该值比您在算法中使用的任何值都小 - 例如,如果您对1e-9
值进行操作,请选择 1e-20
)。
适当的行为取决于函数的规范。该函数可以在没有任何检查的情况下编写(这适用于符合 IEEE 标准的浮点数学);它可以检查 0 并抛出异常;它可以检查 0 并中止;它可以检查 0 并简单地返回。所有这些行为都是合理的,没有上下文就不可能说出最佳选择是什么。这就像问"我要去旅行;我应该开车还是坐飞机?
相关文章:
- 没有找到相关文章