【问题标题】:Divide by zero prevention除以零预防
【发布时间】:2014-12-12 17:00:37
【问题描述】:

什么是 1.#INF 以及为什么转换为 floatdouble 会防止除以 0 导致崩溃?
另外,关于如何防止被0除的任何好主意? (就像任何宏或模板一样)?

int nQuota = 0;

int nZero = 3 / nQuota; //crash
cout << nZero << endl;

float fZero = 2 / nQuota; //crash
cout << fZero << endl;

如果我改用:

int nZero = 3 / (float)nQuota;
cout << nZero << endl;
//Output = -2147483648

float fZero = 2 / (float)nQuota;
cout << fZero << endl;
//Output = 1.#INF

【问题讨论】:

标签: c++


【解决方案1】:

1.#INF 是正无穷大。当你将一个正浮点数除以零时,你会得到它(如果你将浮点数零本身除以零,那么结果将是“不是数字”)。

另一方面,如果你将一个整数除以零,程序就会崩溃。

float fZero = 2 / nQuota; 崩溃的原因是因为/ 运算符的两个操作数都是整数,所以除法是对整数进行的。然后将结果存储在浮点数中并不重要; C++ 没有目标类型的概念。

为什么将正无穷大转换为整数是最小的整数,我不知道。

【讨论】:

  • -2147483648 是 1.#INF 转换为整数。
  • C 规范似乎没有指定将NaN 或无限浮点值转换为整数的结果。 “如果浮点值是无穷大或 NaN,或者如果浮点值的整数部分超出整数类型的范围,则会引发 ''invalid'' 浮点异常并且结果值未指定。”
  • @mkb 好点。我应该包括“在我的机器上运行时”。
【解决方案2】:

为什么使用 (float) 或 (double) 可以防止除以 0 导致崩溃?

不一定。当涉及到浮点时,该标准是惊人的备用。现在大多数系统都使用 IEEE 浮点标准,这表示除以零的默认操作是返回 ±infinity 而不是崩溃。您可以通过启用适当的浮点异常使其崩溃。

请注意:浮点异常模型和 C++ 异常模型的唯一共同点是“异常”一词。在我工作的每台机器上,浮点异常都不会引发 C++ 异常。

另外,关于如何防止被 0 除的任何好主意?

  1. 简单的答案:不要这样做。
    这是其中之一“医生,医生,我这样做会很痛!”种情况。所以不要这样做!

  2. 确保除数不为零。
    对作为用户输入的除数进行完整性检查。始终过滤您的用户输入以保持理智。当数字应该是数百万时,用户输入的值为零将导致除了溢出之外的各种破坏。对中间值进行完整性检查。

  3. 启用浮点异常。
    让默认行为允许错误(这些几乎总是错误)未经检查是恕我直言,标准委员会的一个大错误。使用默认值,那些无穷大和非数字最终会将所有内容变成 Inf 或 NaN。
    默认应该是停止其轨道中的浮点错误,并允许发生 1.0/0.0 和 0.0/0.0 之类的事情。情况并非如此,因此您必须启用这些陷阱。这样做,您通常可以在短时间内找到问题的原因。

  4. 编写自定义除法、自定义乘法、自定义平方根、自定义正弦等函数。
    不幸的是,这是许多安全关键软件系统必须采取的途径。这是一种皇家的痛苦。选项 #1 已退出,因为它只是一厢情愿。选项#3 不可用,因为不允许系统崩溃。选项#2 仍然是一个好主意,但它并不总是有效,因为坏数据总是有办法潜入。这是墨菲定律。

顺便说一句,这个问题比仅仅除以零要糟糕一些。 10200/10-200 也会溢出。

【讨论】:

    【解决方案3】:

    您通常会检查以确保您没有被零除。除非 nQuota 具有合法值,否则下面的代码并不是特别有用,但它确实可以防止崩溃

    int nQuota = 0;
    int nZero = 0;
    float fZero = 0;
    if (nQuota)
        nZero = 3 / nQuota;
    cout << nZero << endl;
    
    if (nQuota)
        fZero = 2 / nQuota;
    cout << fZero << endl;
    

    【讨论】:

    • 有点简单,但它就像一个魅力。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-12
    • 1970-01-01
    • 2016-02-18
    相关资源
    最近更新 更多