前言:在工作中,談到有小數點的加減乘除都會想到用BigDecimal來解決,但是有很多人對於double或者float為啥會丟失精度一臉茫然。還有BigDecimal是怎麼解決的?話不多說,我們開始吧。
1.浮點數是啥?
浮點數是電腦用來表示小數的資料型,採用科學計數法。在java中,double是雙精度,64位,浮點數,預設是0.0d。 float是單一精確度,32位元.浮點數,預設為0.0f;
double 尾數(23 bit)
double 符號位元(1bit) 關係式(11 bit) 尾數(52 bit)
float在記憶體中指數是8bit,由於階碼實際儲存的是
float,記憶體中指數是8bit,由於階碼實際儲存的是##float指數的移碼,假設指數的真值是e,階碼為E,則有E=e (2^n-1 -1)。其中 2^n-1 -1是IEEE754標準規定的指數偏移量,根據這個公式我們可以得到 2^8 -1=127。於是,float的指數範圍為-128 127,而double的指數範圍為-1024 1023。其中負指數決定了浮點數所能表達的絕對值最小的非零數;而正指數決定了浮點數所能表達的絕對值最大的數,也即決定了浮點數的值範圍。
float的範圍為-2^128 ~ 2^127,也即-3.40E 38 ~ 3.40E 38;
double的範圍為-2^1024 ~ 2^1023,也即-1.79E 308 ~ 1.79E 3082.走進失真之科學計數法 我們先說說科學計數法,科學計數法是一種簡化計數的方法,用來近似表示一個極大或極小且位數較多的數,對於位數較小的數值,科學計數法沒有什麼優勢,但對於位數較多的數值其計數方法的優勢就非常明顯了。例如:光的速速是300000000公尺/秒,全世界人口數大約是6100000000。類似光的速度和世界人口數這樣大數值的數,讀、寫都很不方便,所以光的速度可以寫成3*10^8,全世界人口數可以寫成6.1*10^9。所以計算機用科學計數法表示光速是3E8,世界人口數大約是6.1E9。我們小時候玩計算器喜歡瘋狂的累加或累減,到最後計算器就會顯示下圖。這就是科學計數法顯示的結果
電腦在處理資料都涉及到資料的轉換和各種複雜運算,例如,不同單位換算,不同進制(如二進制十進制)換算等,很多除法運算不能除盡,例如10÷3=3.3333.....無窮無盡,而精度是有限的,3.3333333x3並不等於10,經過複雜的處理後得到的十進制數據並不精確,精度越高越精確。 float和double的精度是由尾數的位數來決定的,其整數部分始終是一個隱含著的“1”,由於它是不變的,故不能對精度造成影響。 float:2^23 = 8388608,一共七位,由於最左為1的一位省略了,這意味著最多能表示8位數: 28388608 = 167777216 。有8位有效數字,但絕對能保證的為7位,也即float的精度為7~8位有效數字;double:2^52 = 4503599627370496,一共16位,同理,double的精度為16~17位元.
如遇到
double型別 0.3-0.1的情況。需要將0.3轉成二進位在運算
0.3 * 2 = 0.6 => .0 (.6)取0剩0.6
0.6 * 2 = 1.2 => .01 (. 2)取1剩0.2
0.2 * 2 = 0.4 => .010 (.4)取0剩0.4
3.總結
看完上面,大概清楚了為啥浮點數會有精確度問題。簡單來說float和double類型主要是為了科學計算和工程計算而設計,他們執行二進制浮點運算,這是為了在廣泛的數值範圍上提供較為精確的快速近和計算而精心設計的。然而,他們並沒有提供完全精確的結果,所以不應該被用於精確的結果的場合。浮點數達到一定大的數會自動使用科學計數法,這樣的表示只是近似真實數而不等於真實數。當十進制小數位轉換二進制的時候也會出現無限循環或超過浮點數尾數的長度。
4.那我們要怎麼用BigDecimal來解?
大家看下面的兩個輸出
輸出結果:
0.299999999999999988897769753748434595763683319091796832##.阿里的程式碼約束外掛程式已經標註警告,讓我使用String參數的建構方法來建立BigDecimal。因為double不能精確地表示為0.3(任何有限長度的二進位),所以構造方法傳遞的值也是不完全等於0.3。大家在使用BigDecimal的時候一定要用String參數的建構方法來建立。說到這裡,是木頭有還有好奇的寶寶有疑問,BigDecimal的原理是啥?為啥它就沒有問題呢?其實原理很簡單,BigDecimal是不可變的,可以用來表示任意精確度的帶符號十進位數。 double之所以會出問題,是因為小數點轉二進位遺失精確度。 BigDecimal在處理的時候把十進制小數擴大N倍讓它在整數上進行計算,並保留相應的精度資訊。至於BigDecimal是怎麼保存的可以翻閱一下原始碼。
常見問題
欄位進行學習!以上是double浮點數運算為啥會失去精確度的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

Dreamweaver Mac版
視覺化網頁開發工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SAP NetWeaver Server Adapter for Eclipse
將Eclipse與SAP NetWeaver應用伺服器整合。

WebStorm Mac版
好用的JavaScript開發工具