「踩坑系列」使用long類型處理金額,科學計數法導致金額轉大寫異常

2020-12-20 紙鶴視界

1. 踩坑經歷

上周,一個用戶反饋他創建的某個銷售單無法打開,但其餘銷售單都可以正常打開,當時查看了生產環境的ERROR日誌,發現拋了這樣的異常:java.lang.NumberFormatException: For input string: "E"。

相信大家對這個異常都不陌生,很顯然,是因為將字符串轉換為數字時拋出的,比如下面這樣:

但仔細查看了用戶報錯的單據,也沒有發現哪裡有輸入「E」這樣的字符串(請原諒我第一時間沒有想到是科學計數法造成的,哈哈),最後把生產環境的這條數據插入到了開發環境中,定位到原來是因為將金額轉換為大寫時導致的,報錯的關鍵代碼如下所示:

String totalAmountStr = String.valueOf(totalAmount / 100.0);String amountCN = MoneyUtils.toChinese(totalAmountStr);其中totalAmount是一個long類型的變量,之所以除以100.0,是因為我們資料庫中存儲金額都是按為單位存儲的(相信很多小夥伴也是這麼存儲的),第2行代碼主要是為了將金額轉換為大寫,比如將105000.50轉換為壹拾萬零伍仟元伍角。

用戶報錯的那個單據,totalAmount為2700萬,轉換為分就是:2700000000,執行完totalAmount / 100.0,輸出結果竟然是2.7E7,而不是預期的27000000,因此導致了異常:java.lang.NumberFormatException: For input string: "E"。

最後的解決方案是將金額轉換為BigDecimal來處理,代碼修改為如下所示:

String totalAmountStr = new BigDecimal(String.valueOf(totalAmount)).divide(new BigDecimal("100"),2, RoundingMode.HALF_UP).toString();String amountCN = MoneyUtils.toChinese(totalAmountStr);2. 原因分析

在Java中,當浮點數(float、double)的整數部分達到8位及以上,會以科學計數法表示,如下所示:

double firstAmount = 2700000D;double secondAmount = 27000000D;double thirdAmount = 2700000.25D;double fourthAmount = 27000000.25D;System.out.println(firstAmount);System.out.println(secondAmount);System.out.println(thirdAmount);System.out.println(fourthAmount);

默默數了下,整數部分8位的話,都是千萬級別了,估計遇到這個問題的用戶很豪,哈哈。

所以使用double來表示金額,當金額遇到科學計數法時,就會顯示不正常、甚至造成一些意想不到的異常。

3. 解決方案

如果不想用科學計數法顯示,而是顯示金額本身,有以下2種解決方案:

使用NumberFormat使用BigDecimal3.1 方案一:使用NumberFormat

使用NumberFormat的方法如下所示:

NumberFormat numberFormat = NumberFormat.getInstance();numberFormat.setGroupingUsed(false);double secondAmount = 27000000D;double fourthAmount = 27000000.25D;System.out.println(numberFormat.format(secondAmount));System.out.println(numberFormat.format(fourthAmount));

當將numberFormat.setGroupingUsed(false);注釋掉或者修改為numberFormat.setGroupingUsed(true);時,輸出結果就變為了:

3.2 方案二:使用BigDecimal(推薦)

使用BigDecimal的方法如下所示:

double secondAmount = 27000000D;double fourthAmount = 27000000.25D;System.out.println(new BigDecimal(String.valueOf(secondAmount)).setScale(2,RoundingMode.HALF_UP).toString());System.out.println(new BigDecimal(String.valueOf(fourthAmount)).setScale(2,RoundingMode.HALF_UP).toString());

相比而言,我更推薦使用BigDecimal的這種方案。

關於BigDecimal的更多用法,可以查看我寫的另一篇博客:Java BigDecimal使用指南。

相關焦點

  • 人民幣大寫金額怎麼寫?小寫金額轉大寫怎麼弄?
    人民幣大寫金額怎麼寫?小寫金額轉大寫怎麼弄?有的時候寫支票或者欠款單等等需要運用到大寫金額,但是把小寫金額轉成大寫,到底應該怎麼做呢?接下來小昭就把自己常用的方法介紹出來,希望對大家有所幫助。用Excel表格把小寫金額轉換成大寫是很方便,我們以「8935」這個金額為例。
  • Excel中的小寫金額轉換成大寫格式,財務必學技巧!
    在財務工作中,金額轉大寫是幾乎天天要用到的,在Excel裡面通過以下的技巧,輕鬆的實現。1、沒有小數的數字對於沒有小數的數字,也就是金額具體到元,不計較角和分的,可以使用這種簡單方法選中金額,按CTRL+1,調出自定義單元格格式,在數字裡面選擇特殊,選擇中文大寫數字最終的結果:上面是技巧法
  • 票據金額的中文大寫和數字不一致時怎麼辦?
    作為從事多年票據業務的小融來講,分享票據知識一直都是我非常願意做的事情,今天小融要和大夥說一說票據金額的中文大寫和數字不一致時怎樣辦?感興趣的朋友可以耐心往下閱讀:我國票據法第8條規定:「票據金額以中文大寫和數碼同時記載,二者必須一致,二者不一致的,票據無效。」票據的基本職能是支付金錢或結清往來金額和帳目,票據金額是票據職能的最重要體現,票據金額的高低決定票據價值的高低。
  • 日本公布今年度科學研究補助金額的分配
    日本公布今年度科學研究補助金額的分配     日本文部科學省4月底公布今年度科學研究補助金額的分配說明。科學研究經費的補助,乃是為了振興日本的學術,因此,從人文、社會科學至自然科學等所有領域中特別優秀、有獨創性、或具前瞻性的發展之研究人員或團隊,均是補助的對象。主要目的在於提升大學等的學術研究,並進而鞏固日本的研究基礎。
  • 大數據語言,Java的八大基本數據類型
    整數字面量(127-128)默認是int類型,如果不超出聲明類型的範圍,則可以給出小類型直接賦值(不需要強記,在編寫程序過程中會逐漸理解)。使用整數類型要注意取值範圍,(-128~127)之間的整數字面量可以直接賦值給byte類型,Java會自動處理符號位,同理,short類型也是一樣的(極少使用)。
  • Excel表格中的數字金額如何快速批量變成中文大寫金額模式
    當你在日常工作中碰到需要將數字金額批量快速變成中文大寫金額的時候,你一般是通過什麼方式來實現呢?如果您還沒有想好的話,不妨看看下文,希望對您有點啟發。本教程以Excel2013中的表格數據為例,表格中包含數字金額,如圖所示。複製數字金額單元格區域,然後以數字形式粘貼到B列中對應的單元格。
  • 一文讀懂Java基本數據類型
    byte類型,Java會自動處理符號位,如-8在計算機中以1111 1111 1111 1111 1111 1111 1111 1000表示,如果使用byte = -8語句賦值,則Java自動截掉前面的24位,同理,short類型也是一樣(short極少使用)。
  • 他體驗小米之家買下「全商品套餐」!一看金額大驚:我暈,這麼貴
    他體驗小米之家買下「全商品套餐」!一看金額大驚:我暈,這麼貴▲小米之家販賣的產品種類繁多。小米除了賣手機,產品也橫跨電視、PC等各種家電、配件,被不少人戲稱是「小米雜貨鋪」,果粉會把iPhone、MacBook、Apple Watch和iPad買齊,稱為「蘋果全家桶」,近日就有人到小米之家說要「買全所有產品」,因為品項繁多,最後的金額也讓他嚇了一跳。
  • 辦公室財務人員必備技能:EXCEL如何將數字金額轉換為大寫形式?
    使用場景:在工作表輸入一些財務數據的時候,除了輸入數字的金額外,有時候還需要輸入大寫金額,但每次用輸入法輸入漢字大寫金額都非常麻煩,有方法可以直接將阿拉伯數字的金額轉換為漢字的大寫金額嗎?解決方法:EXCEL本身有內置的將阿拉伯數字轉換為中文大寫數字的功能。比如我們這裡有一個報價單,我們需要將F10單元格的數字轉換為中文大寫數字。我們將F10單元格選中後,點擊滑鼠的右鍵,選擇「設置單元格格式」。
  • 會計必須會,Excel人民幣小寫轉大寫快速輸入方法
    會計在工作中,經常遇到要在Excel中輸入人民幣大寫的情況。如果,你每次都是在手工一個一個漢字錄入,然後再一個字一個字的檢查是否正確,那麼,你真OUT了。其實,在Excel中人民幣大寫快速錄入的方法非常多,使用公式可以,使用VBA也可以,甚至很多輸入法都有這功能。
  • 「入坑指南 6」《如龍》系列
    今天給大家帶來的是《入坑指南》的第6期,《如龍》系列(官方中文譯作《人中之龍》系列)。由於該系列比較長,圖片分成了兩頁,大家請不要忘掉還有第2頁。《如龍》系列最新的「正傳」作品正在開發當中,我們現在還不知道它的準確標題,只知道主人公名叫「春日一番」。《如龍》系列外傳《如龍》系列外傳共有3部,等於是把「正傳」裡的角色再利用所製作的遊戲。
  • Excel中的大小寫金額轉換,技巧法和函數法,職場必學技巧
    財務工作中,經常需要將小寫的數字,轉換成大寫的數字,有兩種方法輕鬆解決,技巧法以及函數法。小寫轉大寫技巧法我們選中單元格,然後右鍵,設置單元格格式(快捷鍵是CTRL+1),在彈出的設置單元格格式窗口中,在數字格式裡面,選擇特殊,選擇中文大寫數字,操作動圖如下所示:小寫轉大寫函數法在2013及版本以上的OFFICE中,內置了一個NUMBERSTRING
  • 「入坑指南 8」《戰神》系列
    今天給大家帶來的是《入坑指南》的第8期,《戰神》系列。有什麼意見建議還請大家踴躍留言,謝謝~《戰神》系列的命名乍看起來十分散亂,有的是數字序號,有的是副標題形式,譯名又不太統一……這裡就為大家梳理一下。
  • 重學Java 設計模式:實戰策略模式「模擬多種營銷類型優惠券,折扣...
    四、案例場景模擬場景模擬;商品支付使用營銷優惠券「在本案例中我們模擬在購買商品時候使用的各種類型優惠券(滿減、直減、折扣、n元購)」這個場景幾乎也是大家的一個日常購物省錢渠道,購買商品的時候都希望找一些優惠券,讓購買的商品更加實惠。
  • 「python學習手冊-筆記」003.數值類型
    003.數值類型本系列文章是我個人學習《python學習手冊(第五版)》的學習筆記,其中大部分內容為該書的總結和個人理解,小部分內容為相關知識點的擴展。非商業用途轉載請註明作者和出處;商業用途請聯繫本人(gaoyang1019@hotmail.com)獲取許可。
  • 存款單上大小寫金額不同如何確定款額
    王某提出異議,說當時存款是30000元,因自己不識字,大寫是多少不清楚,但0和3還是認得的,當時數了是四個0,也就知道是存了30000元。銀行堅持只能按3000元兌付,雙方發生糾紛。王某訴至法院,經審查,王某所持的存單大寫為參仟元,小寫為30000元。庭審中,銀行提交了經王某加蓋了私章的由銀行工作人員填寫的存款憑單,大小寫均為3000元,覆核員也對存款憑單現金進行覆核,認為帳款相符。
  • 尚學堂知識整理:Java double數據類型
    double數據類型使用64位來存儲浮點數。double值也稱為雙精度浮點數。它可以表示一個最小為4.9 x 10^-324,最大為1.7 x 10^308的數字。它可以是正的或負的。Double字面量double字面量值可以用以下兩種格式表示:l 十進位數字格式l 科學計數法
  • 開票金額和收入確認金額是否必須一致?
    所得稅收入確認情況比較複雜,不同收入類型可能判斷標準有所不同,但《國家稅務總局關於確認企業所得稅收入若干問題的通知》(國稅函[2008]875號)還是給出了一個基本原則:企業銷售收入的確認,必須遵循權責發生制原則和實質重於形式原則。
  • Longchamp「瓏驤」獨家支持法國卡菲舞團北京公演
    2013年4月,北京——法國高級皮具品牌Longchamp「瓏驤」 宣布,將於今年再次攜手法國文化中心「中法文化之春」藝術節,獨家支持卡菲舞團北京公演,上演舞蹈《有機體》(Yo Gee Ti)。
  • 財務必備知識:如何在EXCEL裡將阿拉伯數字轉換為中文大寫金額
    在中文世界裡,只要是涉及到正規的財務類數據,基本就會標配一個小寫的阿拉伯數字,再加一個大寫的中文數字,這樣才能降低數據後期被人為篡改的可能性,保證合同等文件的有效性。EXCEL裡面其實有內置的數字大小寫轉換功能,我們隨便在A1單元格輸入一個數字,然後選擇「設置單元格格式」,選擇「特殊」,再選擇右邊的「中文大寫數字」,就可以直接將小寫的阿拉伯數字轉換為大寫的中文數字了。