11

什么是1.#INF以及为什么要强制转换为 a 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
4

3 回答 3

14

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

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

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

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

于 2012-07-02T19:34:44.977 回答
3

为什么使用 (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 仍然是一个好主意,但它并不总是有效,因为坏数据总是有办法潜入。这是墨菲定律。

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

于 2012-07-02T20:28:39.257 回答
2

您通常会检查以确保您没有被零除。除非 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;
于 2012-07-02T19:39:22.350 回答