66

下面的语句java.lang.ArithmeticException: / by zero很明显。

System.out.println(0/0);

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

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

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

它显示Infinity.

以下语句NaN毫无例外地产生 (Not a Number)。

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)......

4

6 回答 6

61

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

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

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

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

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

于 2012-10-18T12:16:32.150 回答
17

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

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

除以整数 0 不在 IEEE 754 中,并且会生成异常 - 没有其他方法可以指示错误,因为int无法表示NaNor Inf

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

于 2012-10-18T12:16:40.260 回答
11

超越无限

class DoubleDivision {

    public static void main(String[] args) {
        System.out.println(5.0/0.0);
    }
}

上面的代码和你提到的片段给出了infinity.

为什么 Java 使用Doubles 来表示小数。二进制不能完全表示一个数字,它只能表示一个近似值,因此 Java 的 double 也不能。

想象一个非常接近于零的数字。如果您知道微积分,请想象一个为零的极限。变量将接近零到某个可以想象的微小距离,但永远不会完全相等。你可以想象,对吧?好吧,假设这个数字对于 Java 来说需要如此高的精度来表示,它放弃并调用它,0.0因为它没有一个好的替代方案。这就是这里发生的事情。任何常规数除以接近于零的超接近数基本上是无穷大。试试看:5 / (10^-100)

另请参阅部分:数学错误中的特殊浮点值以获取更多信息:)

相关问题:为什么 1/0 给出错误但 1.0/0/0 给出 inf

更新: setINT中没有无穷大和NaN值,而 float 确实有无穷大和NaN值。(根据java遵循的IEEE 754标准)

于 2012-10-18T12:09:10.950 回答
5

当除以零时,计算机无法将结果表示为数字。计算机需要发出信号表明结果不是数字。

对于浮点值,它可以产生一个特殊的非数字标记值,因为有一些不代表数字的 32 位 (for float) 和 64 位 (for double) 位模式,因此可以解释为 not -a 数字 ( NaN)。

对于使用常见二进制补码方案(如 Java 要求)的整数值,所有 32 位(for int)和 64 位(for long)位模式都表示一个数字。因此计算机无法使用哨兵报告问题。它必须以某种方式“带外”报告问题。抛出异常是为 Java 选择的带外方法。

于 2012-10-18T12:16:02.250 回答
3

Java 遵循 IEEE 754 标准,该标准定义了在被零除的情况下默认返回的值。http://en.wikipedia.org/wiki/IEEE_754#Exception_handling

除以零(对有限操作数的运算给出精确的无限结果,例如 1/0 或 log(0))(默认返回 ±infinity)。

于 2012-10-18T12:15:30.670 回答
0
import java.util.Scanner;

public class Division {

    public static void main(String[] args) {
        int a, b;
        float result;

        Scanner input = new Scanner(System.in);
        System.out.println("Enter value for a : ");
        a = input.nextInt();

        System.out.println("Enter value for b : ");
        b = input.nextInt();

        try {
            /* here we used "if clause" because result will be in float
             note: Here result is in float, so JVM Cant Catch Exception.
             if we Try to Divide with Zero with Float Values It gives Output as
             Divided by Zero is Infinity */
            if (b != 0) {
                result = (float) a / b;
                System.out.println("Result of " + a + " divided by " + b + " is : " + result);
            } else // here result will be in integer so Jvm can easily Catch The Exception
            {
                result = a / b;
            }
        } catch (ArithmeticException e) {
            System.out.println("Sorry Division By Zero Is Not Possible");
        }
    }
}

/* Ouput :
Enter value for a :2
Enter value for b : 7
Result of 2 divided by 7 is : 0.2857143 */

 /* Ouput :
Enter value for a : 16
Enter value for b : 0
Sorry Division By Zero Is Not Possible */
于 2014-09-18T11:41:12.050 回答