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

时间:2012-10-18 12:05:25

标签: java arithmeticexception dividebyzeroexception

以下语句引人注目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(非数字),没有例外。

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

6 个答案:

答案 0 :(得分:55)

简而言之,这就是它在IEEE-754标准中指定的方式,这是Java Floating-Point Operations所基于的标准。

  

Why doesn't division by zero (or overflow, or underflow) stop the program or trigger an error? Why does a standard on numbers include "not-a-number" (NaN)?

     

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

     

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

     

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

答案 1 :(得分:15)

就是这样,因为这就是IEEE 754定义它的方式。

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

整数0除以IEEE 754未涵盖,并生成异常 - 没有其他方法可以指示错误,因为int无法代表NaNInf

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

答案 2 :(得分:11)

无限及超越

class DoubleDivision {

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

上面的代码以及您提到的代码段infinity

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

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

有关详细信息,请参阅Math Errors处的特殊浮点值部分:)

相关问题:why does 1/0 give error but 1.0/0/0 give inf

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

答案 3 :(得分:5)

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

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

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

答案 4 :(得分:3)

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

  

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

答案 5 :(得分: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 */