我有以下C程序:
#include <stdio.h>
int main()
{
double x=0;
double y=0/x;
if (y==1)
printf("y=1\n");
else
printf("y=%f\n",y);
if (y!=1)
printf("y!=1\n");
else
printf("y=%f\n",y);
return 0;
}
我得到的输出是
y=nan
y!=1
但是当我换线的时候 double x = 0; 至 int x = 0; 输出变为
Floating point exception
任何人都可以解释原因吗?
答案 0 :(得分:2)
您正在使用整数运算导致除0/0
(这是无效的,并产生您看到的异常)。无论y
的类型如何,首先评估的是0/x
。
当x
被声明为double
时,零也会转换为double
,并且使用浮点运算执行操作。
当x
被声明为int
时,您将一个int
0除以另一个,结果无效。
答案 1 :(得分:1)
由于IEEE 754,在对浮点数进行非法操作时会产生NaN(例如0/0
,∞×0
或sqrt(−1)
)。
实际上有两种NaN,信号和安静。用一个 在任何算术运算中发信号通知NaN(包括数值) 比较)将导致“无效”异常。使用安静的NaN 只会导致结果为NaN。
标准指定的NaN的表示有一些 可用于编码错误类型的未指定位;但 该编码没有标准。理论上,信号NaNs 运行时系统可以使用它来扩展浮点数 使用其他特殊值,而不会减慢计算速度 普通价值观。但是,这些扩展似乎并不常见。
此外,维基百科对此integer division by zero说:
整数除零通常与浮动不同 因为结果没有整数表示。一些 处理器在尝试划分时产生异常 整数为零,虽然其他人只会继续并生成一个 分裂的结果不正确。结果取决于如何划分 实现,可以是零,或有时是最大的 可能的整数。
答案 2 :(得分:0)
检查整数数据类型的最小值和最大值。您将看到未定义或纳米结果不在其范围内。
阅读此what every computer scientist should know about floating point.
答案 3 :(得分:0)
整数除以0是非法的,不予处理。另一方面,浮动值使用NaN在C
中处理。以下如何工作。
int x=0;
double y = 0.0 / x;
答案 4 :(得分:0)
IEE754中有一个特殊的位模式,表示{em>浮点除以零错误的结果为NaN
。
然而,在使用整数运算时没有这样的表示,因此系统必须抛出异常而不是返回NaN
。
答案 5 :(得分:0)
如果您将int
除以int
,则可以除以0。
0/0
为NaN
。
int x=0;
double y=0/x; //0/0 as ints **after that** casted to double. You can use
double z=0.0/x; //or
double t=0/(double)x; // to avoid exception and get NaN
答案 6 :(得分:-1)
浮点本身就是将实数建模到有限的精度。只有有限数量的位模式,但是无数(连续!)数量的实数。它当然是最好的,将最接近的可表示的真实值返回给它的确切输入。答案太小而无法直接表示,而是由零表示。除以零是实数中的误差。然而,在浮点时,因为零可能来自这些非常小的答案,所以将x / 0.0(对于正x)视为“正无穷大”或“太大而无法表示”可能是有用的。这对于x = 0.0不再有用。
我们可以说最好的是将零除零实际上是“把一些小的东西划分为零,除了零之外的小东西,除了零以外不能被告知”。这是什么答案?嗯,对于0/0的确切情况没有答案,并且没有好的方法来处理它。它取决于相对的大小,因此处理器基本上耸了耸肩并且说“我失去了所有精度 - 我给你的任何结果都会误导”,返回非数字。
相反,当将整数除以零时,除数实际上只能精确地为零。没有办法给它一致的含义,所以当你的代码要求答案时,它确实在做一些非法的事情。
(它是第二种情况下的整数除法,但不是第一种,因为C的推广规则可以作为整数文字,而且由于两边都是整数,除法是整数除法。例如,x
是一个双倍的事实会导致红利被提升一倍。如果你将0
替换为0.0
,它将是一个浮点除法,无论是类型x
。)