为什么用浮点(或双精度)数字除以零不会抛出java.lang.ArithmeticException:/在Java中被零

以下语句抛出显而易见。java.lang.ArithmeticException: / by zero

System.out.println(0/0);

因为文字被认为是文字,并且在整数算术中不允许除以零。0int

但是,以下情况不会引发任何异常,例如 。java.lang.ArithmeticException: / by zero

int a = 0;
double b = 6.199;
System.out.println((b/a));

它显示 。Infinity

以下语句生成(不是数字)无一例外。NaN

System.out.println(0D/0); //or 0.0/0, or 0.0/0.0 or 0/0.0 - floating point arithmetic.

在这种情况下,两个操作数都被视为双精度。


同样,以下语句不会引发任何异常。

double div1 = 0D/0; //or 0D/0D
double div2 = 0/0D; //or 0D/0D

System.out.printf("div1 = %s : div2 = %s%n", div1, div2);
System.out.printf("div1 == div2 : %b%n", div1 == div2);
System.out.printf("div1 == div1 : %b%n", div1 == div1);
System.out.printf("div2 == div2 : %b%n", div2 == div2);
System.out.printf("Double.NaN == Double.NaN : %b%n", Double.NaN == Double.NaN);
System.out.printf("Float.NaN == Float.NaN : %b%n", Float.NaN == Float.NaN);

它们产生以下输出。

div1 = NaN : div2 = NaN
div1 == div2 : false
div1 == div1 : false
div2 == div2 : false
Double.NaN == Double.NaN : false
Float.NaN == Float.NaN : false

它们都返回 为什么使用浮点数或双精度数允许此操作(除以零)?false.


顺便说一句,我可以理解浮点数(双精度数)的值表示正无穷大负无穷大而不是数字()...NaN


答案 1

简而言之,这就是IEEE-754标准中指定的方式,这就是Java的浮点运算所基于的。

为什么不除以零(或溢出,或下溢)停止程序或触发错误?为什么数字标准包括“非数字”(NaN)?

754 型号鼓励强大的计划。它不仅适用于数值分析师,还适用于电子表格用户,数据库系统甚至咖啡壶。NaN 和无穷大的传播规则允许无关紧要的异常消失。同样,逐渐下溢在精度范围内保持误差属性。

当特殊情况需要注意时,可以通过陷阱立即检查它们,或者在方便的时候通过状态标志进行检查。陷阱可以用来停止程序,但不可恢复的情况极为罕见。对于嵌入式系统或网络代理来说,简单地停止程序不是一种选择。更常见的情况是,陷阱会记录诊断信息或替换有效结果。

标志提供可预测的控制流和速度。它们的使用要求程序员了解异常条件,但标志粘性允许程序员延迟处理异常条件,直到必要时。


答案 2

之所以如此,是因为IEEE 754就是这样定义的。

除以浮点 0.0 得到 NaN 或 +/-Inf,具体取决于分子是否为 0。

IEEE 754 未涵盖整型 0 除法,并生成异常 - 没有其他方法可以指示错误,因为 不能表示 或 。intNaNInf

生成异常类似于 x86 微处理器上由除以零生成的(软件)。INT