BigDecimal 被拼多多的"砍一刀"應用到了極致

恆生LIGHT雲社群發表於2022-01-20

作者:幻好 來源: 恆生LIGHT雲社群

概述

近日,“拼多多砍價, 砍價永遠差一刀”登上了熱搜,而這個功能在我們周圍的親朋好友中都有過親身體驗。

本次事件具體就去年3月,上海律師劉宇航當時參加了拼多多的“砍價免費拿”活動,領取了一張“超級免單卡”,但邀請多人砍價後,始終差“0.9%”。劉宇航以拼多多在提供網路服務時涉嫌違背誠實信用原則,使用虛假資料隱瞞規則已構成欺詐為由,向法院遞交了起訴材料。在案件審理中,針對劉宇航的起訴以及由此引發的質疑,拼多多表示,因頁面顯示百分比位數有限,所以他們把一個至少小數點後有6位數以上的百分比,省略顯示為0.9%,砍價頁面顯示的0.9%不是0.9%,而是0.9996427%。

image-20220119084743848.png

本文主要透過這一現實場景,來思考其背後相關的技術實現——Java中精確小數計算。

BigDecimal

應用背景

在Java中 JDK 中提供的 float 和 double 的資料型別,其主要設計目標是為了科學計算和工程計算,由於其執行的二進位制浮點運算,在某些場景下並不能提供精確的結果。比如:

System.out.println(0.1 + 0.2);// 輸出0. 30000000000000004

一個簡單的加法運算,在輸出的結果上並不能保證結果的準確性。其主要原因是在CPU中,表示的浮點數由兩個部分組成:指數和尾數,這樣一般都會導致失去一定的精確度,有些浮點數運算也會產生一定的誤差,浮點數的值實際上是由一個特定的數學公式計算得到的。如:2.4的二進位制表示並非就是精確的1.5。反而最為接近的二進位制表示是 1.59999999999999。

所以在許多需要精確小數計算的商業場景(如支付,商城等),通常需要採用 java.math.BigDecimal 類來進行精確計算。

操作使用

建立 BigDecimal 物件

BigDecimal bigDecimal = new BigDecimal("2022.01054");

通常建議使用 String 型別的構造方法,建立 BigDecimal 物件,雖然也可以使用 Double 型別的構造方法,但是前面就說過,浮點數本來就不準確,因此轉換的 BigDecimal 物件也會不精確。

格式化小數

// 向零方向舍入System.out.println(bigDecimal.setScale(3, BigDecimal.ROUND_DOWN));// 輸出2022.010
 // 向遠離0的方向舍入,進位處理new BigDecimal(4.32579).setScale(4, BigDecimal.ROUND_UP);// 輸出2022.011
 // 向(距離)最近的一邊舍入,除非兩邊(的距離)是相等,如果是這樣,向上舍入: >=5new BigDecimal(4.32575).setScale(4, BigDecimal.ROUND_HALF_UP);// 輸出2022.011
 // 向(距離)最近的一邊舍入,除非兩邊(的距離)是相等,如果是這樣,向下舍入: >5new BigDecimal(4.32575).setScale(4, BigDecimal.ROUND_HALF_DOWN);// 輸出2022.010

加減乘除運算

// 推薦用字串的形式初始化BigDecimal numFri = new BigDecimal("0.0888");
BigDecimal numSec = new BigDecimal("0.2222");
// 加法BigDecimal resultByAdd = numFri.add(numSec);
// 減法BigDecimal resultBySub = numFri.subtract(numSec);
// 乘法BigDecimal resultByMul = numFri.multiply(numSec);
// 除法BigDecimal resultBydiv = numFri.divide(numSec,20,BigDecimal.ROUND_HALF_UP);
// 絕對值BigDecimal resultByAbs = numFri.abs();

BigDecimal 物件在減乘除時,最終都返回的是一個新的 BigDecimal 物件,因為 BigIntegerBigDecimal 都是不可變的(immutable)的
,在進行每一步運算時,都會產生一個新的物件

總結

在需要精確計算的重要場景,使用 BigDecimal,同時推薦使用 String 型別的建構函式建立 BigDecimal 物件。


想向技術大佬們多多取經?開發中遇到的問題何處探討?如何獲取金融科技海量資源?

恆生LIGHT雲社群,由恆生電子搭建的金融科技專業社群平臺,分享實用技術乾貨、資源資料、金融科技行業趨勢,擁抱所有金融開發者。

掃描下方小程式二維碼,加入我們!


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70001864/viewspace-2853193/,如需轉載,請註明出處,否則將追究法律責任。

相關文章