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