28

关于除以零,标准说:

C99 6.5.5p5 - / 运算符的结果是第一个操作数除以第二个的商;% 运算符的结果是余数。在这两种操作中,如果第二个操作数的值为零,则行为未定义。

C++03 5.6.4 - 二元 / 运算符产生商,二元 % 运算符产生第一个表达式除以第二个表达式的余数。如果 / 或 % 的第二个操作数为零,则行为未定义。

如果我们从表面上看上面的段落,答案显然是两种语言的未定义行为。但是,如果我们进一步查看 C99 标准,我们会看到以下段落似乎是矛盾的 (1):

C99 7.12p4 - 宏 INFINITY 扩展为浮点类型的常量表达式,表示正或无符号无穷大(如果可用);

标准是否有某种黄金法则,即未定义的行为不能被(可能)矛盾的陈述所取代?除此之外,我认为如果您的实现定义了 INFINITY 宏,那么除以零被定义为这样的结论是不合理的。但是,如果您的实现没有定义这样的宏,则行为是未定义的。

我很好奇这两种语言在这个问题上的共识是什么(如果有的话)。如果我们谈论整数除法int i = 1 / 0与浮点除法,答案会改变float i = 1.0 / 0.0吗?

注意 (1) C++03 标准谈到了<cmath>包含 INFINITY 宏的库。

4

8 回答 8

30

我看不出有什么矛盾。除以零是未定义的,句号。在引用的文本中的任何地方都没有提到“......除非定义了 INFINITY” 。

请注意,在数学中没有任何地方定义 1 / 0 = infinity。人们可能会这样解释,但这是一种个人的“捷径”风格解释,而不是一个可靠的事实。

于 2010-06-09T08:24:05.563 回答
14

1 / 0 不是无穷大,只是

lim 1/x = ∞ (x -> +0)

于 2010-06-09T08:24:23.850 回答
9

这不是一个最纯粹的数学问题,而是一个 C/C++ 问题。

  • 根据所有现代 C 编译器/FPU 使用的 IEEE 754 标准,我们有
    • 3.0 / 0.0 = INF
    • 0.0 / 0.0 = NaN
    • -3.0 / 0.0 = -INF

FPU 将有一个状态标志,如果需要,您可以设置它以生成异常,但这不是常态。

当 INF 是有用的结果时,INF 对于避免分支非常有用。请参阅此处的讨论

http://people.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF

于 2016-07-20T15:56:05.260 回答
4

为什么会呢?

这在数学上没有意义,一般来说,1/ x在数学中并不是被定义为 ∞ 的。此外,您至少还需要另外两种情况:-1/ x和 0/ x也不能等于 ∞。

一般参见除以零,特别是关于计算机算术的部分。

于 2010-06-09T08:22:25.520 回答
2

定义__STDC_IEC_559__的实现需要遵守附件 F 中给出的要求,这反过来又需要与 IEC 60559 一致的浮点语义。该标准对未定义的实现的浮点除零的行为没有要求__STDC_IEC_559__,但对于那些定义它的人来说。在 IEC 60559 指定行为但 C 标准未指定的情况下,C 标准__STDC_IEC_559__要求定义的编译器按照 IEC 标准中的描述运行。

根据 IEC 60559(或美国标准 IEEE-754)的定义,零除以零产生 NaN,浮点数除以正零或字面常量零产生与被除数具有相同符号的 INF 值,除法浮点数除以负零会产生具有相反符号的 INF。

于 2016-07-20T19:41:43.980 回答
1

我只有C99草稿。在§7.12/4 中它说:

    INFINITY

扩展为浮点类型的常量表达式,表示正或无符号无穷大(如果可用);否则为float 在翻译时溢出的类型正常量。

请注意,INFINITY可以根据浮点溢出来定义,不一定要被零除。

于 2010-06-09T08:28:56.103 回答
1

对于 INFINITY 宏:在 IEEE754 标准中有一个明确的编码来表示 +/- 无穷大,即如果所有指数位都被设置并且所有小数位都被清除(如果小数位被设置,它表示 NaN)

使用我的编译器,如果返回 INFINITIY (int) INFINITY == -2147483648,那么计算结果为的表达式int i = 1/0肯定会产生错误的结果

于 2010-06-09T08:54:23.483 回答
0

底线,C99(根据您的报价)在“实现定义”的上下文中没有说明任何关于 INFINITY 的内容。其次,您引用的内容并未显示“未定义行为”的不一致含义。


[引用维基百科的未定义行为页面]“在 C 和 C++ 中,也使用实现定义的行为,其中语言标准没有指定行为,但实现必须选择一种行为,并且需要记录并遵守它选择的规则。”

更准确地说,标准意味着“实现定义的”(我认为只是),因为“实现定义的”是标准的特定属性,所以当它使用这些词来表示所做出的陈述时。C99 7.12p4 的引用没有提到“实现定义”。

[来自 C99 标准(后期草案)]“未定义行为:在使用不可移植或错误程序构造或错误数据时的行为,本国际标准对此没有要求”

请注意,对未定义的行为“没有要求”!

[C99 ..]“实现定义的行为:未指定的行为,每个实现都记录了如何做出选择”

[C99 ..]“未指定的行为:使用未指定的值,或本国际标准提供两种或多种可能性并且在任何情况下都没有对其选择的进一步要求强加的其他行为”

文档是实现定义的行为的要求。

于 2014-09-26T15:15:12.147 回答