浮點(diǎn)數(shù)

1,浮點(diǎn)數(shù)基本知識(shí)

Java 語(yǔ)言支持兩種基本的浮點(diǎn)類型: float 和 double ,以及與它們對(duì)應(yīng)的包裝類 Float 和 Double 。它們都依據(jù) IEEE 754 標(biāo)準(zhǔn),該標(biāo)準(zhǔn)定義了32 位單精度和 64 位雙精度兩種浮點(diǎn)二進(jìn)制小數(shù)標(biāo)準(zhǔn)。

IEEE 754 用科學(xué)記數(shù)法以底數(shù)為 2 的小數(shù)來表示浮點(diǎn)數(shù)。

  • 32位單精度浮點(diǎn)數(shù)float,用 1 位表示數(shù)字的符號(hào),用 8 位表示指數(shù),用 23 位表示尾數(shù),即小數(shù)部分,如2^23 = 8388608,一共七位,這意味著最多能有7位有效數(shù)字,但絕對(duì)能保證的為6位,也即float的精度為6~7位有效數(shù)字。
  • 64位雙精度浮點(diǎn)數(shù)double,用1 位表示數(shù)字的符號(hào),用 11 位表示指數(shù),用52 位表示尾數(shù),即小數(shù)部分,如2^52 = 4503599627370496,一共16位,也即double的精度為15~16位。
  • 作為有符號(hào)整數(shù)的指數(shù)可以有正負(fù)之分,也即決定了浮點(diǎn)數(shù)的取值范圍。小數(shù)部分用二進(jìn)制(底數(shù) 2)小數(shù)來表示,這意味著最高位對(duì)應(yīng)著值 ?(2 -1),第二位對(duì)應(yīng)著 ?(2 -2),依此類推。

IEEE 浮點(diǎn)值的格式如圖 1 所示:

圖 1. IEEE 754 浮點(diǎn)數(shù)的格式

2,浮點(diǎn)數(shù)比較

在java中浮點(diǎn)型默認(rèn)是double的,浮點(diǎn)數(shù)都要在計(jì)算機(jī)里轉(zhuǎn)換進(jìn)行二進(jìn)制存儲(chǔ),這就涉及到數(shù)據(jù)精度。
例如,十進(jìn)制小數(shù)0.9表示成二進(jìn)制數(shù)為:1100100100100......后面部分將無限循環(huán)下去,很顯然,小數(shù)的二進(jìn)制表示有時(shí)是不可能精確的。比如double類型表示小數(shù)部分只有52位,當(dāng)向后計(jì)算52位后基數(shù)還不為0,那后面的部分只能通過四舍五入得到一個(gè)近似值,此時(shí)就造成精度丟失。
所以,當(dāng)浮點(diǎn)數(shù)進(jìn)行比較時(shí),由于浮點(diǎn)數(shù)的二進(jìn)制表示本身就不準(zhǔn)確,比較大小時(shí)就會(huì)出現(xiàn)錯(cuò)誤。例如float f1 = 20014999f == float f2 = 20015000f。

因此,有個(gè)原則:

  • 程序中應(yīng)盡量避免浮點(diǎn)數(shù)的比較
  • float、double類型的運(yùn)算往往都不準(zhǔn)確

3,BigDecimal

要想獲得理想的結(jié)果,應(yīng)該使用BigDecimal來獲得更精確的計(jì)算。
在《Effective Java》這本書中也提到這個(gè)原則,float和double只能用來做科學(xué)計(jì)算或者是工程計(jì)算,在商業(yè)計(jì)算中我們要用java.math.BigDecimal。

BigDecimal夠造方法的參數(shù)類型有4種,其中的兩個(gè)用BigInteger構(gòu)造,另一個(gè)是用double構(gòu)造,還有一個(gè)使用String構(gòu)造。應(yīng)該避免使用double構(gòu)造BigDecimal,因?yàn)椋河行?shù)字用double根本無法精確表示,傳給BigDecimal構(gòu)造方法時(shí)就已經(jīng)不精確了。
比如,new BigDecimal(0.1)得到的值是0.1000000000000000055511151231257827021181583404541015625。使用new BigDecimal("0.1")得到的值是0.1。因此,如果需要精確計(jì)算,用String構(gòu)造BigDecimal,避免用double構(gòu)造。

BigDecimal都是不可變的(immutable)的,在進(jìn)行每一步運(yùn)算時(shí),都會(huì)產(chǎn)生一個(gè)新的對(duì)象,由于創(chuàng)建對(duì)象會(huì)引起開銷,因此它們不適合于大量的數(shù)學(xué)運(yùn)算,所以a.add(b);雖然做了加法操作,但是a并沒有保存加操作后的值,正確的用法應(yīng)該是a=a.add(b)。

4,小數(shù)點(diǎn)位數(shù)保留

  • String s=String.format("%.2f",d),表示保留小數(shù)點(diǎn)后任意兩位小數(shù),并且符合四舍五入的規(guī)則。
  • DecimalFormat df = new DecimalFormat("0.00"),不管傳入的任何值,均保留兩位小數(shù)。
  • DecimalFormat df = new DecimalFormat("#.##"),則保留小數(shù)點(diǎn)后面不為0的兩位小數(shù),這種寫法不能保證保留2為小數(shù),但能保證最后一位數(shù)不為0。
  • double d = 1.000;
    BigDecimal bd=new BigDecimal(d);
    double d1=bd.setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue();
    System.out.println(d1);
    輸出結(jié)果:1.0
    若double d=0,輸出結(jié)果為0.0;
    若double d=1.999,輸出結(jié)果為2.0;
    若double d=1.89,輸出結(jié)果為1.89;
    這種寫法若小數(shù)點(diǎn)后均為零,則保留一位小數(shù),并且有四舍五入的規(guī)則。

參考:
https://www.ibm.com/developerworks/cn/java/j-jtp0114/index.html
http://blog.csdn.net/ccecwg/article/details/22286873
http://www.cnblogs.com/chenfei0801/p/3672177.html
http://www.ituring.com.cn/article/216160
http://swiftlet.net/archives/798
http://www.lxweimin.com/p/00fff555986b

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評(píng)論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,615評(píng)論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,606評(píng)論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評(píng)論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,826評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,227評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評(píng)論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,447評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,992評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,807評(píng)論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,001評(píng)論 1 370
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評(píng)論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,243評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評(píng)論 1 287
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,709評(píng)論 3 393
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,996評(píng)論 2 374

推薦閱讀更多精彩內(nèi)容