防止被零除的适当行为

Appropriate behaviour to prevent division by zero

本文关键字:      更新时间:2023-10-16

我们被要求使用堆栈上的内存设计一个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);
}

由于您必须从运算符返回一个值,因此您有两个选择:

  1. 抛出异常(绝对首选)
  2. 返回一个由三个NaN组成的向量。

顺便说一下,你不应该怀疑浮点值是否等于零,因为你会得到很多假阴性。由于特定的浮点运算,您应该将除数与非常小的值进行比较(该值比您在算法中使用的任何值都小 - 例如,如果您对1e-9值进行操作,请选择 1e-20 )。

适当的行为取决于函数的规范。该函数可以在没有任何检查的情况下编写(这适用于符合 IEEE 标准的浮点数学);它可以检查 0 并抛出异常;它可以检查 0 并中止;它可以检查 0 并简单地返回。所有这些行为都是合理的,没有上下文就不可能说出最佳选择是什么。这就像问"我要去旅行;我应该开车还是坐飞机?

相关文章:
  • 没有找到相关文章