为什么Java中的数字除以零无穷大?

为什么要在Java中使用以下代码

System.out.println(new Integer(1)/ new Double(0)); 

打印’无限’而不是未定义。 这不是数学错误吗?

在数学中,有许多不同的结构支持算术。 最突出的那些,例如自然数,整数和实数,不包括无穷大。 在这些系统中,不支持除零。

其他系统确实包括至少一个无穷大。 例如,参见真实的投射线 。 它允许除以零。

只有一种方法可以知道在特定系统中数学定义或未定义的内容 – 研究该系统。

类似地,操作是否可交换(op b == b op a)和/或关联(op(b op c)==(a op b)op c)取决于系统和操作。

IEEE 754二进制浮点是具有有限元素集的系统,包括两个无穷大。 加法和乘法都是可交换的,但不是联想的。 Java实数和双重算术都是基于它的。 Java语言规范是确定Java浮点算法中定义的内容或唯一定义内容的唯一方法。

使用浮点的许多最差错误的基础是假设浮点数是实数,而不是有效但不同的系统。

这与Java遵循的关于浮点的IEEE 754标准一致。

不,你不能在数学中除以零,但在Java Infinity中对于new Integer(1)/ new Double(0)是正确的。 new Integer(0)/ new Double(0)将是未定义的( NaN )。

Java遵循IEEE标准,因此对于诸如此类的浮点运算, Infinity是正确的。 如果它是1/0 ,则会发生ArithmeticException ,因为在整数除法中,不允许除零; 无穷大没有int表示。

具体来说,在JLS中,第15.17.2节 :

[I] f整数除法中除数的值为0,然后抛出ArithmeticException。

浮点除法的结果由IEEE 754算法的规则决定:

将零除以零导致NaN除以零的非零有限值导致有符号无穷大。

简而言之:浮点数可以表示无穷大(甚至是产生非数字值的运算),因此导致此结果的操作(例如,除以0)是有效的。

在今天的浮点标准设计中,一个更好的设计决策是允许除零之类的东西产生一个特殊的标记值,表示某些东西超出了范围,而不是使程序崩溃。 然后,使用结果的代码可以决定这样的标记值表示主要问题或次要问题的程度。 例如,绘制函数的程序可以简单地省略在绘制其余值时无法计算值的点。

浮点数很少会输出为真值。 相反,它将输出一些足以识别其值的字符串。 将非零数除以零时生成的标记值打印为“无穷大”,但这并不意味着它在数学上是无限的。 相反,它意味着它是用于表示结果的标记值,该结果与大于大约2 ^ 1024并且应该排名大于任何其他定义结果的任何其他数字无法区分。 对于与任何小于 – (2 ^ 1024)的任何其他数字无法区分的结果,存在另一个标记值,并且该排名应低于任何其他定义的结果。 对于无法计算但不适合任何类别的结果,存在第三种结果。

使用相同的标记进行超过2 ^ 1024的计算并将正数除以零的原因是,当将非常大的正数除以非常小的正数时,可能出现这两种情况。 如果这种比较的结果是“正无穷大”,排序高于其他所有,即使除以最无穷小的正数,它应该在除以该数字的“一半”时保留(其舍入为零)。