日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

bigdecimal 保留两位小数_一律使用 BigDecimal,避免后患?

發布時間:2023/12/10 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 bigdecimal 保留两位小数_一律使用 BigDecimal,避免后患? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

你知道的越多,不知道的就越多,業余的像一棵小草!

你來,我們一起精進!你不來,我和你的競爭對手一起精進!

編輯:業余草

zhuanlan.zhihu.com/p/94144867

推薦:https://www.xttblog.com/?p=5116

一律使用 BigDecimal,避免后患?

一、背景

總在項目中看到 Double 與 BigDecimal 被用錯的情況,竟然有人告訴我:“一律使用 BigDecimal,避免后患”,我相信這位兄弟肯定是被精度問題搞蒙了,因此我想同步一下我的使用姿勢,僅提供參考。

二、兩種類型使用過程中都有可能出坑

  • double 的計算時容易出現不精確的問題
  • double 的小數部分容易出現使用二進制無法準確表示。

    如十進制的0.1,0.2,0.3,0.4 都不能準確表示成二進制。

    具體原因相信大家都懂,我就不多說了。如果有不懂的可以私信我或者評論留言!

  • dobule 的 = 比較要注意
  • dobule 小數超過 15 位的相等比較就不一定對了。都是 true。

  • BigDecimal 的除法除不盡會出現異常:ArithmeticException
  • 所以,使用 BigDecimal 進行除法運算一定要有精度!

  • new BigDecimal(double) 結果也許不是你想要的
  • 一般情況下都不使用 new BigDecimal(double) 應該使用 BigDecimal.valueOf(double)。

    BigDecimal?d1?=?BigDecimal.valueOf(12.3);
    //結果是12.3?你預期的
    BigDecimal?d2?=?new?BigDecimal(12.3);
    //結果是12.300000000000000710542735760100185871124267578125

    我想 12.300000000000000710542735760100185871124267578125 肯定不是你想要的結果,因此 new BigDecimal(double) 可能會產生不是你預期的結果,原理可以自行看一下底層源代碼,還是比較容易搞懂的。

    另:BigDecimal.valueOf(xxx) 是靜態工廠類,永遠優先于構造函數(摘自《Effecitve java》,此書也是非常推薦的一本經典書)

  • BigDecimal 是不可變對象
  • 如原來 d1=1.11 ,又加了一個數 2.11,這種操作要注意結果要指向新對象。

    任何針對BigDecimal對象的修改都會產生一個新對象;

    BigDecimal?newValue?=?BigDecimal.valueOf(1.2222).add(BigDecimal.valueOf(2.33333));

    BigDecimal?newValue?=?BigDecimal.valueOf(1.2222).setScale(2);

    總之每次修改都要重新指向新對象,才能保證計算結果是對的。

  • BigDecimal 比較大小操作不方便,畢竟是對象操作
  • 比較大小和相等都使用 compareTo,如果需要返回大數或小數可使用 max,min。且注意不能使用 equals。

    三、效率比較

    比如:1 累加到 1000000(以本人機器 MacBookPro 2018 i7 2.2G)double 比 BigDecimal 快大約 10 倍

    double: 2ms

    BigDecimal:16ms

    四、優缺點總結

    double 的優缺點:

  • double在計算過程中容易出現丟失精度問題

  • 使用方便,有包裝類,可自動拆裝箱,計算效率高

  • BigDecimal 的優缺點:

  • 精度準確,但做除法時要注意除不盡的異常

  • BigDecimal 是對象類型,也沒有自動拆封箱機制,操作起來總是有些不順手

  • 五、使用場景推薦

    涉及到精準計算如金額,一定要使用 BigDecimal 或轉成 long 或 int 計算。

    若不需要精準的,如一些統計值:(本身就沒有精確值)。

    用戶平均價格,店鋪評分,用戶經緯度等本就沒有精準值一說的推薦使用 double 或 float,寫代碼更方便,計算效率也高得多。

    值得一提的說,如果 double 或 float 僅是用于傳值,并不會有精度問題,但如果參與了計算就要小心了。要區分是不是需要精準值,如果需要精準值,需要轉成 BigDecimal 計算以后再轉成 double。

    但依然約定在 DTO 定義金額時使用 BigDecimal 或整形值,是為了減少或避免 double 參與金額計算的機會,避免出 bug。

    其他1:代碼中看到碰到讓我覺得有問題的地方

    以下代碼在不同的類中抓出來的覺得用得不太恰當的地方:

    代碼中真的不需要那么多地方使用 BigDecimal,相反用到 BigDecimal 的地方并不多,反而用 Double 的地方更多。以上代碼我希望的方式是:

    提醒:DTO 中盡量使用包裝類,防止反系列化時 null 的造成的格式轉換異常

    分析

    經緯度:一般業務代碼中也不太會去計算,僅用于傳給地圖api等,經緯度一般用于計算距離,如果保留到 6 位小數時其實已經是 1 米級別的了,也滿足絕大多數場景了,因此使用 Double 是確實是可行的;

    店鋪平均消費:本身就是一個歸納統計值,也一般用來比較大小做參考,因此也用不著 BigDecimal;

    當前價格:這個不一樣了,為了減少 double 參與金錢計算,統一使用 BigDecimal 代替帶有小數的金額;

    其他2:關于 Mysql 中如何選用這兩種類型

  • 首先與 java 不同的是 mysql 是用來持久化數據的,而 java 中使用的數據一般更多的是過一下內存;

  • 數據庫都要除了指定數據類型指外還需要指定精度,因此在 DB 中 Double 計算時精度的丟失比 Java 高得多;

  • 因為 Java 默認精確到 15-16 位了;

  • 更改數據類型的成本,Mysql 比 Java 代碼要難得多;
  • 考慮到以上與 java 中不同幾點,做點個人使用總結:

  • 與商業金融相關字段要使用 Decimal 來表示,如金額,費率等字段;

  • 參與各類計算如加,減,乘,除,sum,avg 等等,也要使用 Decimal;

  • 經緯度,可以使用 double 來表示,這個可參考 Java,只要保證精度范圍即可;

  • 如果確實不確定使用什么 double 或 Decimal 哪種類型合適,那最好使用 Decimal,畢竟穩定,安全高于一切;

  • 注:阿里的編碼規范中強調統一帶小數的類型一律使用 Decimal 類型,也是有道理的,使用Decimal 可以大大減少計算踩坑的概率。

    總結

    以上是生活随笔為你收集整理的bigdecimal 保留两位小数_一律使用 BigDecimal,避免后患?的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。