为什么Java中要出现下面的代码
System.out.println(new Integer(1)/ new Double(0));
打印“无限”而不是未定义。这不是数学上的错误吗?
为什么Java中要出现下面的代码
System.out.println(new Integer(1)/ new Double(0));
打印“无限”而不是未定义。这不是数学上的错误吗?
这与 Java 遵循的IEEE 754浮点标准一致。
在数学中,有许多不同的结构支持算术。最突出的数字,例如自然数、整数和实数,不包括无穷大。在这些系统中,不支持除以零。
其他系统确实包括至少一个无穷大。例如,参见实射影线。它确实允许除以零。
只有一种方法可以知道在特定系统中数学定义或未定义的内容 - 研究该系统。
类似地,操作是否可交换(a op b == b op a)和/或关联(a op (b op c) == (a op b) op c)取决于系统和操作。
IEEE 754 二进制浮点是一个具有有限元素集的系统,包括两个无穷大。加法和乘法都是可交换的,但不是结合的。Java real 和 double 算术都是基于它的。Java 语言规范是确定 Java 浮点运算中定义或未定义的唯一方法。
使用浮点数的许多最严重错误的基础是假设浮点数是实数,而不是有效但不同的系统。
不,您不能在数学中除以零,但在 JavaInfinity
中对于new Integer(1)/ new Double(0)
. new Integer(0)/ new Double(0)
将是未定义的 ( NaN
)。
Java 遵循 IEEE 标准,因此对于诸如此类的浮点运算Infinity
是正确的。如果是1/0
,ArithmeticException
就会发生 an ,因为在整数除法中,不允许除以零;没有int
无穷大的表示。
具体来说,在JLS 中,第 15.17.2 节:
[I]如果整数除法中除数的值为 0,则抛出 ArithmeticException。
和
浮点除法的结果由 IEEE 754 算术规则确定:
零除以零导致 NaN 非零有限值除以零导致有符号无穷大。
在今天的浮点标准设计中,一个更好的设计决策是允许除以零之类的东西来产生一个特殊的标记值,该值表明某些东西超出了范围,而不是使程序崩溃。然后,使用结果的代码可以决定这种标记值在多大程度上表示主要问题或次要问题。例如,绘制函数的程序可能会在绘制其余部分时简单地省略无法计算值的点。
很少将浮点数作为其真值输出。相反,它将输出为足以识别其值的一些字符串。将非零数除以零时生成的标记值打印为“无穷大”,但这并不意味着它在数学上是无穷大。相反,这意味着它是用于表示一个结果的哨兵值,该结果与任何其他大于大约 2^1024 的数字都无法区分,并且应该比任何其他定义的结果排名更高。对于一个与小于 -(2^1024) 的任何其他数字无法区分的结果存在另一个标记值,并且其排名应该小于任何其他定义的结果。第三个存在于无法计算但不适合任一类别的结果。
对超过 2^1024 的计算和正数除以零使用相同标记的原因是,当将一个非常大的正数除以一个非常小的正数时,两种情况都会出现。如果这种比较的结果是“正无穷大”,则排序高于一切,即使除以最小的最小正数时,除以该数字的“一半”(四舍五入为零)时,它也应该保持不变。
简而言之:浮点数可以表示无穷大(甚至可以表示产生非数字值的操作),因此导致这种情况的操作(例如除以 0)是有效的。