Dividing by zero in C
当我编译程序时:
1 2 3 4 5 6 7 8 9 10 11
| #include <stdio.h>
int main (void)
{
int x , y = 0;
x = 1 / y ;
printf("x = %d
", x );
return 0;
} |
它给出了"浮点异常(核心转储)"
但是,当我编译时:
1 2 3 4 5 6 7 8 9 10 11
| #include <stdio.h>
int main (void)
{
double x , y = 0;
x = 1 / y ;
printf("x = %f
", x );
return 0;
} |
它打印"x = inf"
如果你使用double,为什么它将x作为无限值返回,但如果你使用int则会返回错误?
-
整数没有inf或NaN。
-
整数除法引发处理器异常,而平衡点除法具有表示。
-
一个相关的问题stackoverflow.com/questions/23878400/…
-
@WeatherVane - 非常漂亮的新图标/ avitar ......
-
@ DavidC.Rankin你自己看起来不错!
-
主要原因是1 / 0 => inf在数学上是不正确的,但浮点数是不精确的值,可能是在你的计算中,除数太小而它被舍入到0,所以它仍然是 最好只产生一些结果而不是让整个程序崩溃,以便你知道它出错的地方。 这就是IEEE 754在大多数情况下的作用。 然而,对整数而言,这不是一个明智的事情,整数不能代表无穷大。
-
请注意,您可以使用1 / 1e-309获得无穷大,这比数学无穷小小几个数量级;-)
C标准明确指出除以零对于整数或浮点操作数具有未定义的行为。
C11 6.5.5第5段:
The result of the / operator is the quotient from the division of the
first operand by the second; the result of the % operator is the
remainder. In both operations, if the value of the second operand is
zero, the behavior is undefined.
未定义的行为意味着标准没有说明发生的事情。它可能产生一个有意义或无意义的结果,它可能会崩溃,或者它可以像标准的笑话一样,让恶魔飞出你的鼻子。 (当然后者不会发生,但如果确实如此,它就不会违反C标准。)
与整数类型不同,浮点类型通常具有不表示数字的特殊值。 IEEE浮点标准规定,除以零可以产生无穷大的结果,这正是您的实现所做的。整数没有"无穷大"值。 (注意,C实现可能符合也可能不符合IEEE浮点标准。)
这个问题讨论了IEEE浮点中除零的语义。
C标准定义了对算术类型操作数的除零行为是未定义的(参见,例如,此在线C标准草案):
6.5.5 Multiplicative operators
2 Each of the operands shall have arithmetic type. The operands of the
% operator shall have integer type.
5 The result of the / operator is the quotient from the division of
the first operand by the second; the result of the % operator is the
remainder. In both operations, if the value of the second operand is
zero, the behavior is undefined.
此规则明确包含浮点值,因为术语算术类型表示整数值和浮点值:
6.2.5 Types
18 Integer and floating types are collectively called arithmetic
types.
因此,您的两个示例实际上都是未定义的行为,并且每个编译器可以自己指定如何处理您的语句。因此,如果编译器将整数除零视为异常,则它是符合标准的,而浮点除零则给出特殊值inf。注意:标准没有定义必须如此。
浮点变量实际上可以存储表示无穷大的值。 (它是在math.h中定义的值INFINITY)但是没有无穷大的整数表示,所以唯一要做的就是失败。
-
这不是唯一要做的事情。可能会发生无穷无尽的事情,比如恶魔可能会从你的鼻子中产生。
-
值得指出的是,无穷大不是将数字除以零的数学上正确的结果 - 相反,结果在数学上是未定义的。
-
@JeremyFriesner:是的,但是IEEE浮点标准确实将Infinity指定为除零的结果(对于某些设置)。 C实现可能符合也可能不符合IEEE。
-
@JeremyFriesner:那么1.0 / 0.0不应该是NaN吗?当你从x(左)( - ∞)或右(+∞)趋向于0时,无限大于1.0 / * x *时起作用。
-
@jxh:stackoverflow.com/q/14682005/827263讨论了除以零的IEEE规则。
-
不是在新手处理器中,通过减法计算它需要花费很多时间。
-
@JeremyFriesner:没有算术的定义。算术来自公理,不同的算术系统适合不同的目的,
-
"所以唯一要做的就是失败。";实际上没有 - 行为是未定义的,人们不能依赖"它失败"(无论"失败"意味着什么)。
-
@StephanLechner实际上IEEE比C标准更适用。
-
@P__J__:工程不是猜测适用哪种规范的过程。它们应该明确说明,理想情况下,具有所需行为的正确设计在逻辑上来自规范。这个问题标记为C而不是IEEE-754,它告诉我们"这个标签应该与关于C语言的一般问题一起使用,如ISO 9899标准中定义的那样(最新版本,9899:2018,除非另有说明 - 也标签c89,c99,C11等版本特定的请求。"所以我们更喜欢C标准作为回答的基础。
-
好的,在C中将整数除以零的结果在技术上是未定义的,但很明显,在OP的机器上它会产生错误。 OP问为什么它会产生错误,而不是他可以依赖这种行为。
-
@EricPostpischil不同意。所有marh硬件和库软件都遵循IEEE而不是标准。硅
-
@P__J__:不,他们没有。即使他们这样做,问题也是关于C,而不是关于硬件或库。
-
@EricPostpischil这个问题无法在不考虑实施的情况下回答。然后它是UB,形成实际的观点,当你做一些数字工作时没有任何意义
-
@P__J__:一个问题的不可用性证明做出假设是荒谬的。什么是合理的是声明C不定义行为,但观察到所获得的结果可能是甚至可能是因为它们的实现使用了IEEE 754的一些特征,这是普遍存在的。请注意,使用IEEE 754的某些功能与符合IEEE 754不同,并且不假设IEEE 754适用。它向OP提供信息,这可以使他们进一步学习和调查,而不会断言未知的陈述。