Division by Zero in Java: Exception, Infinity, or Not a Number – Java中的零除法 异常、无穷大或不是一个数字

最后修改: 2020年 7月 6日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Dividing by zero is an operation that has no meaning in ordinary arithmetic and is, therefore, undefined. In programming, however, while it is often associated with an error, this is not always the case.

除以零是一个在普通算术中没有意义的操作,因此是没有定义的。然而,在编程中,虽然它经常与错误联系在一起,但情况并不总是这样

In this article, we’ll go through what happens when a division by zero occurs in a Java program.

在这篇文章中,我们将了解在Java程序中发生除以0时的情况

According to the Java specification of the division operation, we can identify two different cases of division by zero: integers and floating-point numbers.

根据Java对除法运算的规范,我们可以确定除以0的两种不同情况:整数和浮点数。

2. Integers

2.整数

Firstly, for integers, things are pretty straightforward. Dividing an integer by zero will result in an ArithmeticException:

首先,对于整数来说,事情是非常简单的。整数除以0会导致ArithmeticException

assertThrows(ArithmeticException.class, () -> {
    int result = 12 / 0;
});
assertThrows(ArithmeticException.class, () -> {
    int result = 0 / 0;
});

3. Floating Point Types

3.浮点类型

However, when dealing with floating-point numbers, an exception won’t be thrown:

然而,当处理浮点数时不会抛出一个异常

assertDoesNotThrow(() -> {
    float result = 12f / 0;
});

In order to handle cases like these, Java uses some special numeric values that can represent the results of such an operation: NaN, POSITIVE_INFINITY, and NEGATIVE_INFINITY.

为了处理类似的情况,Java使用了一些特殊的数字值,可以代表这样的操作的结果。NaN, POSITIVE_INFINITY, 和NEGATIVE_INFINITY。

3.1. NaN

3.1. NaN

Let’s start by dividing floating-point zero values by zero:

让我们从将浮点零值除以0开始。

assertEquals(Float.NaN, 0f / 0);
assertEquals(Double.NaN, 0d / 0);

The result in these cases is NaN (not a number).

在这些情况下,结果是NaN(不是一个数字)。

3.2. Infinity

3.2.无限大

Next, let’s divide some non-zero values by zero:

接下来,让我们将一些非零值除以零

assertEquals(Float.POSITIVE_INFINITY, 12f / 0);
assertEquals(Double.POSITIVE_INFINITY, 12d / 0);
assertEquals(Float.NEGATIVE_INFINITY, -12f / 0);
assertEquals(Double.NEGATIVE_INFINITY, -12d / 0);

As we can see, the result is INFINITY, with the sign depending on the sign of the operands.

我们可以看到,结果是INFINITY,,其符号取决于操作数的符号。

Moreover, we can also use the concept of negative zero in order to get to NEGATIVE_INFINITY:

此外,我们还可以使用负零的概念,以达到NEGATIVE_INFINITY

assertEquals(Float.NEGATIVE_INFINITY, 12f / -0f);
assertEquals(Double.NEGATIVE_INFINITY, 12f / -0f);

3.3. Memory Representation

3.3.内存表示法

So, why does integer division by zero throw an exception, while floating-point division by zero does not?

那么,为什么整数除以0会出现异常,而浮点除以0却不会呢?

Let’s look at this from a memory representation perspective. For integers, there is no bit pattern that can be used to store the result of such an operation, while floating-point numbers have values like NaN or INFINITY to be used in cases like these.

让我们从内存表示的角度来看看这个问题。对于整数来说,没有比特模式可以用来存储这种操作的结果,而浮点数有NaNINFINITY这样的值,可以在这种情况下使用。

Now, let’s consider the binary representation of a float as SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF with one bit (S) for the sign, 8 bits (E) for the exponent, and the rest (F) for the mantissa.

现在,让我们考虑浮点的二进制表示法为SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF 有1位(S)为符号,8位(E)为指数,其余(F)为尾数。

In each of the three values NaN, POSITIVE_INFINITY, and NEGATIVE_INFINITY, all bits in the exponent part are set to 1.

NaNPOSITIVE_INFINITY,和NEGATIVE_INFINITY这三个值中,指数部分的所有位都被设置为1。

INFINITY has the mantissa bits all set to 0, while NaN has a non-zero mantissa:

INFINITY的尾数位全部设置为0,而NaN的尾数位非零。

assertEquals(Float.POSITIVE_INFINITY, Float.intBitsToFloat(0b01111111100000000000000000000000));
assertEquals(Float.NEGATIVE_INFINITY, Float.intBitsToFloat(0b11111111100000000000000000000000));
assertEquals(Float.NaN, Float.intBitsToFloat(0b11111111100000010000000000000000));
assertEquals(Float.NaN, Float.intBitsToFloat(0b11111111100000011000000000100000));

4. Summary

4.摘要

To sum things up, in this article we saw how division by zero works in Java.

总结一下,在这篇文章中,我们看到了零除法在Java中的作用。

Values like INFINITY and NaN are available for floating-point numbers but not for integers. As a result, dividing an integer by zero will result in an exception. However, for a float or double, Java allows the operation.

INFINITYNaN这样的值可以用于浮点数,但不能用于整数。因此,用整数除以0会导致一个异常。然而,对于floatdouble,Java允许该操作。

The complete code is available over on GitHub.

完整的代码可在GitHub上获得。