Effective Java(3rd)-Item60 如果需要確切的答案盒使,避免使用float和double

??float 和double 主要用于科學計算和工程計算崩掘。它們執(zhí)行二進制浮點算法,該算法經(jīng)過精心設(shè)計少办,能夠在很大范圍內(nèi)快速提供精確的近似值苞慢。但是,它們不能提供準確的結(jié)果凡泣,也不應(yīng)該在需要精確結(jié)果的地方使用枉疼。float和double類型特別不適合進行貨幣計算因為作為float和double不可能代表0.1(或者任何其他10的負冪)皮假。
??例如,假設(shè)你口袋里有1.03美元骂维,你消費了42美分惹资。你還剩下多少錢?下面是一個簡單的程序片段,試圖回答這個問題:
System.out.println(1.03 - 0.42);
??不幸的是航闺,它輸出了0.6100000000000001褪测。這不是一個特例。假設(shè)你口袋里有一美元潦刃,你買了9臺洗衣機侮措,每臺10美分。你能得到多少零錢?
System.out.println(1.00 - 9 * 0.10);
??根據(jù)這個程序片段乖杠,可以得到0.0999999999999999998美元分扎。
??您可能認為,只需在打印之前將結(jié)果四舍五入就可以解決這個問題胧洒,但不幸的是畏吓,這種方法并不總是有效。例如卫漫,假設(shè)你口袋里有一美元菲饼,你看到一個架子上有一排好吃的糖果,它們的價格僅僅是10美分列赎,20美分,30美分饼煞,以此類推诗越,直到1美元。每買一顆糖掺喻,從10美分的那顆開始感耙,直到你買不起貨架上的下一顆糖持隧。你買了多少糖果,換了多少零錢?這里有一個簡單的程序設(shè)計來解決這個問題:

image.png

??如果你運行這個程序只酥,你會發(fā)現(xiàn)你可以買得起三塊糖褥实,你還有0.399999999999999999美元。這是錯誤的答案!解決這個問題的正確方法是使用BigDecimal裂允、int或long進行貨幣計算损离。
??這里是前一個程序的一個簡單轉(zhuǎn)換,使用BigDecimal類型代替double绝编。注意僻澎,使用BigDecimal的字符串構(gòu)造函數(shù)而不是它的double構(gòu)造函數(shù)。這是為了避免在計算中引入不準確的值[Bloch05, Puzzle 2]:


image.png

??如果你運行修改后的程序十饥,你會發(fā)現(xiàn)你可以用剩下的0美元買四顆糖窟勃。這是正確答案。
??然而逗堵,使用BigDecimal有兩個缺點:它比使用原始算術(shù)類型要不方便得多秉氧,而且速度要慢得多。如果你只解決一個簡單的問題蜒秤,后一種缺點是無關(guān)緊要的汁咏,但前者可能會讓你煩惱。
??使用BigDecimal的另一種方法是使用int或long垦藏,這取決于涉及的數(shù)量梆暖,并自己跟蹤小數(shù)點。在這個例子中掂骏,最明顯的方法是用美分而不是美元來計算轰驳。下面是一個采用這種方法的簡單轉(zhuǎn)換:


image.png

??總之,對于任何需要精確答案的計算弟灼,不要使用float或double级解。如果希望系統(tǒng)跟蹤小數(shù)點,并且不介意不使用基本類型帶來的不便和成本田绑,請使用BigDecimal。
??使用BigDecimal的另一個好處是芒划,它可以完全控制舍入民逼,當執(zhí)行需要舍入的操作時,可以從八種舍入模式中進行選擇疮鲫。如果您使用合法的舍入行為執(zhí)行業(yè)務(wù)計算俊犯,這將非常方便瘫析。如果性能是最重要的咸包,那么您不介意自己跟蹤小數(shù)點烂瘫,而且數(shù)量不是太大坟比,可以使用int或long。如果數(shù)量不超過9位小數(shù)籍琳,可以使用int;如果不超過18位趋急,可以使用long呜达。如果數(shù)量可能超過18位查近,則使用BigDecimal嗦嗡。
本文寫于2019.7.18,歷時1天

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末矮冬,一起剝皮案震驚了整個濱河市胎署,隨后出現(xiàn)的幾起案子琼牧,更是在濱河造成了極大的恐慌,老刑警劉巖趾撵,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件占调,死亡現(xiàn)場離奇詭異,居然都是意外死亡剿涮,警方通過查閱死者的電腦和手機幔虏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瑟蜈,“玉大人铺根,你說我怎么就攤上這事。” “怎么了臣缀?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長脂倦。 經(jīng)常有香客問我赖阻,道長,這世上最難降的妖魔是什么布隔? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮哀军,結(jié)果婚禮上打却,老公的妹妹穿的比我還像新娘猿推。我一直安慰自己蹬叭,他們只是感情好秽五,可當我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布盲再。 她就那樣靜靜地躺著,像睡著了一般坯沪。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上藻糖,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天,我揣著相機與錄音洋满,去河邊找鬼。 笑死驻民,一個胖子當著我的面吹牛回还,可吹牛的內(nèi)容都是我干的柠硕。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼诫咱,長吁一口氣:“原來是場噩夢啊……” “哼竟痰!你這毒婦竟也來了坏快?” 一聲冷哼從身側(cè)響起莽鸿,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎级及,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體县踢,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片索抓。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡毯炮,死狀恐怖逼肯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情桃煎,我是刑警寧澤篮幢,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站为迈,受9級特大地震影響三椿,放射性物質(zhì)發(fā)生泄漏缺菌。R本人自食惡果不足惜搜锰,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一薯嗤、第九天 我趴在偏房一處隱蔽的房頂上張望玻褪。 院中可真熱鬧窟社,春花似錦匣吊、人聲如沸命雀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弦追。三九已至零远,卻和暖如春纬向,著一層夾襖步出監(jiān)牢的瞬間粘捎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工债蓝, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挟憔。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓铣焊,卻偏偏與公主長得像坟募,于是被迫代替她去往敵國和親她紫。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,941評論 2 355

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

  • [{"reportDate": "2018-01-23 23:28:49","fluctuateCause": n...
    加勒比海帶_4bbc閱讀 767評論 1 2
  • 目錄: Android:Android 0.*Android 1.*Android 2.*Android 3.*A...
    敲代碼的令狐蔥閱讀 3,859評論 0 2
  • Spring Boot Test 簡介 Spring Boot提供了大量的實用的注解來幫助我們測試程序。針對測試支...
    傅永德閱讀 987評論 0 6
  • 感謝孔雨教練推薦這部電影鸡岗,本人已經(jīng)很久沒有看過電影或者電視劇脯厨。 看這部電影的時候合武,除了很期待男主角會鼓起勇氣表白,...
    Sara_T閱讀 427評論 0 1
  • 南惹古村距江西宜春溫湯小鎮(zhèn)約四十分鐘的車程桶蝎。小車行駛在蜿蜒而平整的盤山公路上带到,滿眼是茂盛的綠英染,清新的空氣撲面...
    惜福惜福閱讀 966評論 0 5