作者:IT互聯網大叔
https://juejin.im/post/5edcc957e51d4578801683c0
一、引言
在這個浮躁的社會,我們都學會了一種技能,快速學習使用各種開源庫、開源框架,
學習使用各種高端大氣的技術,熱修復、插件化、模塊化、ORM……
這些技能固然重要,但是有時候也要放慢腳步,耐著性子,打打基本功,
不要看不起這些零零碎碎的基礎知識,這些基礎榷訓月累,慢慢的會讓你跟同事拉開差距,
接下來,我們直奔主題,開始我們的基本功,
二、代碼1
System.out.println("1/0=" + 1/0);
大叔的靈魂拷問:
上面的代碼會崩潰嗎?如果不會,會輸出什么呢?
上面的代碼會崩潰嗎?如果不會,會輸出什么呢?
上面的代碼會崩潰嗎?如果不會,會輸出什么呢?
運行直接崩潰,

三、代碼2
我們再來看一行代碼:
System.out.println("1.0/0=" + 1.0/0);
大叔的靈魂拷問:
會崩潰嗎?如果不會,會輸出什么呢?
會崩潰嗎?如果不會,會輸出什么呢?
會崩潰嗎?如果不會,會輸出什么呢?
輸出日志:

四、為什么?
為什么浮點數除以0不會崩潰?
我們先說結論:
因為java的float和double使用了IEEE 754標準,
這個標準規定:浮點數除以0等于正無窮或負無窮,
4.1、Double類的定義
于是我們打開Double這個類來看看,

infinity單詞的意思是:無窮大
NaN是Not a Number的簡稱,也就是非數,
于是,我們發現,正無窮大的定義居然是1.0f/0.0f ,負無窮大的定義為 -1.0f/0.0f,非數的定義為0.0f/0.0f
4.2、代碼段3
我繼續看一個代碼段:
public static void main(String[] args) {
System.out.println("1.0/0=" + 1.0/0);
System.out.println("-1.0/0=" + -1.0/0);
double positiveInfinity = 1.0/0;
double negativeInfinity = -1.0/0;
System.out.println("(positiveInfinity==negativeInfinity)=" + (positiveInfinity==negativeInfinity));
System.out.println();
System.out.println("100.0/0=" + 100.0/0);
System.out.println("-100.0/0=" + -100.0/0);
System.out.println();
System.out.println("0.0/0=" + 0.0/0);
System.out.println("(-0.0==0.0)=" + (-0.0==0.0));
}
大叔的靈魂拷問:
上面的代碼段會輸出什么呢?
上面的代碼段會輸出什么呢?
上面的代碼段會輸出什么呢?
運行結果:


4.3 java語言規范( Java Language Specification)
docs.oracle.com/javase/spec…[1]

注意關鍵詞1:
IEEE 754
java的單精浮點數float和雙精浮點數double,符合IEEE 754標準,
IEEE 754:二進制浮點數算術標準 ,這個標準描述了浮點數的存盤以及處理的一些規范,
注意關鍵詞2
A NaN value is used to represent the result of certain invalid operations such as dividing zero by zero.
翻譯過來的就是:NaN = 0.0/0.0
這也就是我們看到Double類里面NaN的定義,
我們把這個檔案往下翻一些,會發現這么一句:

for example,
1.0/0.0has the value positive infinity, while the value of1.0/-0.0is negative infinity.
翻譯成中文:1.0/0.0 等于正無窮大,1.0/-0.0 等于負無窮大
于是我們明白,浮點數除以0并不會崩潰,他是合法的,是符合IEEE 754規范,
也正是因為 IEEE 754的規范就是這么規定的,所以java才這么實作的,
下面這段來自,維基百科,en.wikipedia.org/wiki/Divisi…[4]

五、有什么用呢?
我們即使知道了,浮點數除以0不會崩潰,知道了IEEE標準,有什么用呢?
很多人都會覺得,費這么大勁,理解了,浮點數除以0不會崩潰,能有什么用呢?平時我們寫代碼都不會除以0,這么騷的操作,我才不會這么干,
是的,這個操作是有點騷,你不會這么干并不代表其他同事不會這么做,而且很可能你這么干了自己不知道,
在我們寫業務代碼的時候,這個知識點,很少很少能用上,
但是當我們剛好遇到除以0導致的bug的時候,這個時候就非常有用,最近我也寫了個全域變數的bug,被同事們打臉,推薦大家看下,
尤其像android的app,用戶在線上遇到的bug,我們無法復現,只能通過日志去分析排查時;
這個時候每個程式員都是福爾摩斯,根據一行行日志線索,配合實際代碼,排查問題的可能性,
如果我們的認知是錯誤的,任何數除以0都會崩潰,那么我們的分析將會直接繞過真相去推理,于是得出結論,怎么可能有bug,不可能的,
于是浪費了很多時間,去收集線索,去推翻我們固有的認知,才能找到真相,
假如我們一開始就有正確的常識,我們就會少走很多彎路,
大叔給大家,講一個作業中真實的故事:
有位同事寫了這么一段代碼
/**
* 速度換算 米/秒
* @param distance 距離,單位米
* @param time 時間,單位秒
*/
float computeSpeed(float distance, long time){
return distance/time;
}
然后有一天突然某同事從另一個行程獲取到資料傳入這個函式,
再然后,突然有一天發現,速度顯示一串很奇怪的數字,
于是……接下來的故事,便如你們所想,
原本1小時就解決的bug,花了5個小時,
也正如,blog開頭的引言所表達的,不要小看這些零零碎碎的知識點,
關注公眾號Java技術堆疊回復"面試"獲取我整理的2020最全面試題及答案,
推薦去我的博客閱讀更多:
1.Java JVM、集合、多執行緒、新特性系列教程
2.Spring MVC、Spring Boot、Spring Cloud 系列教程
3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程
4.Java、后端、架構、阿里巴巴等大廠最新面試題
覺得不錯,別忘了點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/148099.html
標籤:Java
上一篇:推薦 5 款牛逼的代碼編輯器
