为啥整数除以零 1/0 会出错但浮点数 1/0.0 返回“Inf”?

Posted

技术标签:

【中文标题】为啥整数除以零 1/0 会出错但浮点数 1/0.0 返回“Inf”?【英文标题】:Why does integer division by zero 1/0 give error but floating point 1/0.0 returns "Inf"?为什么整数除以零 1/0 会出错但浮点数 1/0.0 返回“Inf”? 【发布时间】:2011-07-14 13:53:18 【问题描述】:

我只是对此感到好奇:

在 Java 中评估 1/0 时,会发生以下异常:

线程“main”中的异常 java.lang.ArithmeticException: / by 零 在 Foo.main(Foo.java:3)

但是1/0.0 被评估为Infinity

public class Foo 
    public static void main (String[] args) 
        System.out.println(1/0.0);
    

为什么会这样?

【问题讨论】:

【参考方案1】:

这是因为整数没有 +/-Inf、NaN 的值,并且不允许除以 0,而浮点数却有这些特殊值。

【讨论】:

对于 NaN 并没有真正的 + 和 - 值。【参考方案2】:

1/0 是两个 int 的除法,并且由于不能除以整数零而引发异常。但是,0.0 是 double 类型的文字,Java 将使用浮点除法。 IEEE 浮点规范具有除以零的特殊值(除其他外),其中之一是 double.Infinity。

如果您对细节感兴趣,浮点规范(通常是神秘的)在 Wikipedia 上有一个页面:http://en.wikipedia.org/wiki/IEEE_754-2008,也可以在线阅读其全文:http://ieeexplore.ieee.org/xpl/mostRecentIssue.jsp?punumber=4610933。

【讨论】:

不幸的是,Java 不允许设置 IEEE 754-2008 陷阱。如果您在代码中编写 1/0.0,则 Infinity 的来源很明显,但如果您从一个处理大量数字的函数中获得 NaN,it's not simple to find out what exactly went wrong。【参考方案3】:

1/0 是整数除法,1/0.0 是浮点除法 - 浮点数可以表示无效值,整数不能。

【讨论】:

【参考方案4】:

IEEE 为浮点数定义了某些标准,其中包括“非数字”以及正无穷和负无穷的定义。这些不适用于整数。

见http://steve.hollasch.net/cgindex/coding/ieeefloat.html

这些特殊情况的原因基本上是舍入错误。浮点数通常总是被截断,因为它们从不精确。另一方面,整数总是精确的。

【讨论】:

【参考方案5】:

fetestexceptfeenableexcept

值得注意的是,底层CPU硬件可以检测0.0 / 0.0的具体情况,并且:

设置一些标志位,可以用ANSI C查询fetestexcept(FE_ALL_EXCEPT) == FE_INVALID 如果使用 feenableexcept(FE_INVALID) glibc 扩展启用了异常,则引发异常

但是,我找不到 Java 是否公开了该功能。

这是一个最小的可运行 C 示例:What is difference between quiet NaN and signaling NaN?

【讨论】:

以上是关于为啥整数除以零 1/0 会出错但浮点数 1/0.0 返回“Inf”?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 C# 允许在浮点类型中将非零数除以零?

浮点数的那点事

在java中的double和float类型数据相除为啥可以除以零

随机浮点数生成

为啥将浮点数除以整数返回 0.0?

为啥 Python 返回 0.0 进行除法? [复制]