

踩坑了!0作为除数,不一定会抛出异常! - why技术
source link: https://www.cnblogs.com/thisiswhy/p/16635585.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

踩坑了!0作为除数,不一定会抛出异常!
你好呀,我是歪歪。
踩坑了啊,又踩坑了啊!
这次踩到一个特别无语的常识坑。知道真相的那一刻,人就是整个麻掉。

先上个代码:
private static double calculate(double a, int b) {
return a / b;
}
你先别问为什么计算不用 BigDecimal,反正程序里面就是有一个类似于这样的方法。
正常用起来也没啥毛病:

注意,我说的是“正常使用看起来没毛病”,不正常使用是怎么样的呢?

看到输出结果是 “Infinity” 的时候,我甚至揉了一下眼睛,以为自己是过于热爱工作,导致用眼过度,看花了。
有一说一,我真没见过这玩意。但是这个单词我认识啊:

在我有限的认知里面, 0 是不可以作为除数的,如果作为除数会抛出异常才对。
但是这个简单的案例打破了我的认知,它不仅没有抛出异常,还给我了一个“无穷大的数”。
在一脸懵逼中,我知道,素材这不就来了嘛。

如果是在使用框架的过程中遇到问题,一般来说我是先自己调试一下,挣扎一波,看看是不是自己的打开方式不对。
但是这个问题太简单了,以至于我甚至找不到调试的角度。
只有直接拿出程序员的祖传技能了:面向浏览器编程。
于是我输入搜索关键字 “Java Infinity”,排在第一的是某博客网站:

我个人是不太喜欢这个网站,所以我按照个人习惯重新搜索了一次:

找到了下面这个链接:
https://www.cnblogs.com/zhisuoyu/p/5314541.html

从这篇文章中我知道了,原来在我的认知里面,0 作为除数会抛出下面这个异常,还有一个前提是“整型运算”:
java.lang.ArithmeticException: / by zero
在 Double 和 Float 里面都定义了“正无穷”和“负无穷”这两个常量:


现在我知道在浮点运算的时候,0 是可以作为除数的。
但是,为什么呢?
Java 里面什么这样设计呢,为什么不一视同仁呢?
博客里面没有写,但是我知道要找到这个问题的答案,这个地方可以去看看:
https://stackoverflow.com/
于是我用 “Java Double Float Infinity” 关键字去查询了一下:

很容易就找到了这个链接:
https://stackoverflow.com/questions/12954193/why-does-division-by-zero-with-floating-point-or-double-precision-numbers-not

这个提问者提出的问题翻译过来,和我前面遇到的问题一模一样:
为什么用 Float 或者 Double 除以零不会抛出 java.lang.ArithmeticExceptionL:/by zero 异常?
这个问题下的高赞回答是这样的:

问题的终极答案就藏在这个高赞回答中,我给你解析一番。

这个高赞回答,其实就只有一句话:
In short, that's the way it's specified in the IEEE-754 standard, which is what Java's Floating-Point Operations are based on.
其他的部分都是引用。
在这一句话中,他提到了两个关键的东西:
- IEEE-754 standard
- Java's Floating-Point Operations
意思就是 Java 的浮点运算是基于 IEEE-754 标准来的。
他给的其中一个超链接是 Java 语言规范:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.2.3

Java 语言规范表示:你要问我为什么,我只能告诉你我遵守的是 IEEE 754 这个国际规范。
所以,别问:

那么这个 IEEE 754 是个什么东西呢?
我也不知道,所以查一下:

好家伙,来头还不小。
IEEE,全称 Institute of Electrical and Electronics Engineers,电气和电子工程师协会。
IEEE 754 的全称是 IEEE Standard for Floating-Point Arithmetic。 表示电气和电子工程师协会制定的浮点运算技术标准。
Standard,标准,你明白吧?
得有一些 Standard,有些事情才好办,不然各自为战,各自兼容,难受的一比。
所以,该标准是为了解决在不同的浮点实现中的各种问题,这些问题使它们难以可靠地使用和移植。
一旦有了标准,大家都遵守,就好办了。
在标准中就规定了对于异常应该如何处理:

来,框起来的部分,跟我大声的朗读一遍:
Division by zero: an operation on finite operands gives an exact infinite result, e.g., 1/0 or log(0). By default, returns ±infinity.
针对“除以 0”异常,IEEE 754 规定:对有限操作数的运算会得到一个精确的无限结果,例如,1/0 或 log(0)。默认情况下,返回 ±infinity。
那么问题又来了?
为什么标准中要这样的规定呢?
在前面提到的高赞回答中,给到了这样的一个链接:
https://web.archive.org/web/20180112211305/http://grouper.ieee.org/groups/754/faq.html#exceptions
这个问题的答案就藏在这个链接里面:

请问:为什么除以零(或溢出,或下溢)不会停止程序或引发错误?
下面给了一大段回复,我尝试着理解了几次,但是我发现有点超纲了,确实不知道具体啥意思。
我个人浅显的认为它要表达的意思是:这玩意使用范围很广,为了程序的稳定性,我不想抛出异常来终止程序,而使用者应该知道我这个“除 0 之后是一个无穷大的数”这样的设定。
所以到底为什么呢?
就到这吧。
就不礼貌了。

看完之后,你只需要记住一句话:在 Java 里面,除数作为 0,不一定会抛出 ArithmeticException,千万不要形成这样的固化思维,从而影响自己排除问题的方向。
Recommend
-
21
PHP PDO PDO::ATTR_SERVER_INFO 抛出异常时会触发一个警告 时间: 2019-07-16 10:11 分类:
-
9
运用@Transactional抛出异常后不回滚 作者: wencst 分类: JAVA,Uncategorized 发布时...
-
9
【前端 · 面试 】JavaScript 之你不一定会的基础题(一)最近我在做前端面试题总结系列,感兴趣的朋友可以添加关注,欢迎指正、交流。争取每个知识点能够多总结一些,...
-
11
高效Java:抛出适合抽象的异常 - Kyle Carter《Effective Java》一书的大部分内容都是聚焦构建一个干净、易懂的 API 以及它如何成为一个伟大库的基础。类的 API 的一部分是任何异常,它可能会抛出已检查(它成为签名的一部分)或未检查的堆栈。作为代码的编写者...
-
6
1. HarmonyOS的方法为何都抛出异常 不管是鸿蒙(HarmonyOS),或是Android、还是其他系统。理解其工作原理最好的方式就是阅读源代码。不过HarmonyOS的所有系统类,跟踪进去,全部是下面的东西。 从反编译后的源代码可以看出,除了类的成员变...
-
9
V2EX › JavaScript 多层嵌套异常捕获/抛出的最佳实践? KirbySD · 21 小时 41 分钟前 · 909 次点...
-
8
V2EX › 程序员 异常抛出后能穿越回代码执行前 debug 吗? AndyAO · 17 小时 45 分钟前 ·...
-
8
首页 > 文章详情 鲍威尔安抚市场:缩减购债不一定会造成破坏 昨天 23:24 3,099 本文来自:金十数据,作者:肖燕燕 鲍威...
-
6
晚上多吃不一定会胖,Cell子刊最新研究颠覆减肥认知
-
4
设计师重构X标志赢好评!但马斯克不一定会喜欢! - 标志情报局
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK