日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

如何使用BigDecimal實現Java開發商業計算

瀏覽:19日期:2022-08-24 11:09:55

前言

今天群里一個初級開發者問為什么測試人員測出來他寫的價格計算模塊有計算偏差的問題,他檢查了半天也沒找出問題。這里小胖哥要提醒你,商業計算請務必使用BigDecimal,浮點做商業運算是不精確的。因為計算機無法使用二進制小數來精確描述我們程序中的十進制小數。《Effective Java》在第48條也推薦“使用BigDecimal來做精確運算”。今天我們就來總結歸納其相關的知識點。

BigDecimal

BigDecimal表示不可變的任意精度帶符號十進制數。它由兩部分組成:

intVal - 未校正精度的整數,類型為BigInteger Scale - 一個32位整數,表示小數點右邊的位數

例如,BigDecimal 3.14的未校正值為314,縮放為2。我們使用BigDecimal進行高精度算術運算。我們還將它用于需要控制比例和舍入行為的計算。如果你的計算是商業計算請務必使用計算精確的BigDecimal 。

構造BigDecimal實例

我們可以從String,character 數組,int,long和BigInteger創建一個BigDecimal對象:

@Testpublic void theValueMatches() { BigDecimal bdFromString = new BigDecimal('0.12'); BigDecimal bdFromCharArray = new BigDecimal(new char[]{’3’, ’.’, ’1’, ’4’, ’1’, ’5’}); BigDecimal bdlFromInt = new BigDecimal(42); BigDecimal bdFromLong = new BigDecimal(123412345678901L); BigInteger bigInteger = BigInteger.probablePrime(100, new Random()); BigDecimal bdFromBigInteger = new BigDecimal(bigInteger); assertEquals('0.12', bdFromString.toString()); assertEquals('3.1415', bdFromCharArray.toString()); assertEquals('42', bdlFromInt.toString()); assertEquals('123412345678901', bdFromLong.toString()); assertEquals(bigInteger.toString(), bdFromBigInteger.toString());}

我們還可以從double創建BigDecimal:

@Testpublic void whenBigDecimalCreatedFromDouble_thenValueMayNotMatch() { BigDecimal bdFromDouble = new BigDecimal(0.1d); assertNotEquals('0.1', bdFromDouble.toString());}

我們發現在這種情況下,結果與預期的結果不同(即0.1)。這是因為:這個轉換結果是double的二進制浮點值的精確十進制表示,其值得結果不是我們可以預測的.我們應該使用String構造函數而不是double構造函數。另外,我們可以使用valueOf靜態方法將double轉換為BigDecimal 或者直接使用其未校正數加小數位數 :

@Testpublic void whenBigDecimalCreatedUsingValueOf_thenValueMatches() { BigDecimal bdFromDouble = BigDecimal.valueOf(0.1d); BigDecimal bigFromLong=BigDecimal.valueOf(1,1); assertEquals('0.1', bdFromDouble.toString()); assertEquals('0.1', bigFromLong.toString());}

在轉換為BigDecimal之前,此方法將double轉換為其String表示形式。此外,它可以重用對象實例。因此,我們應該優先使用valueOf方法來構造函數。

常用API

方法名 對應方法相關用法解釋 abs() 絕對值,scale不變 add(BigDecimal augend) 加,scale為augend和原值scale的較大值 subtract(BigDecimal augend) 減,scale為augend和原值scale的較大值 multiply(BigDecimal multiplicand) 乘,scale為augend和原值scale的和 divide(BigDecimal divisor) 除,原值/divisor,如果不能除盡會拋出異常,scale與原值一致 divide(BigDecimal divisor, int roundingMode) 除,指定舍入方式,scale與原值一致 divide(BigDecimal divisor, int scale, int roundingMode) 除,指定舍入方式和scale remainder(BigDecimal divisor) 取余,scale與原值一致 divideAndRemainder(BigDecimal divisor) 除法運算后返回一個數組存放除盡和余數 如 23/3 返回 {7,2} divideToIntegralValue(BigDecimal divisor) 除,只保留整數部分,但scale仍與原值一致 max(BigDecimal val) 較大值,返回原值與val中的較大值,與結果的scale一致 min(BigDecimal val) 較小值,與結果的scale一致 movePointLeft(int n) 小數點左移,scale為原值scale+n movePointRight(int n) 小數點右移,scale為原值scale+n negate() 取反,scale不變 pow(int n) 冪,原值^n,原值的n次冪 scaleByPowerOfTen(int n) 相當于小數點右移n位,原值*10^n

BigDecimal操作

BigDecimal上的操作就像其他Number類(Integer,Long,Double等)一樣,BigDecimal提供算術和比較操作的操作。它還提供了縮放操作,舍入和格式轉換的操作。它不會使算術運算符(+ - /*)或邏輯運算符(> < | &) 過載。相反,我們使用BigDecimal相應的方法 - 加,減,乘,除和比較。并且BigDecimal具有提取各種屬性的方法。

提取屬性

精度,小數位數和符號:

@Testpublic void whenGettingAttributes_thenExpectedResult() { BigDecimal bd = new BigDecimal('-12345.6789'); assertEquals(9, bd.precision()); assertEquals(4, bd.scale()); assertEquals(-1, bd.signum());}

比較大小

我們使用compareTo方法比較兩個BigDecimal的值:

@Testpublic void whenComparingBigDecimals_thenExpectedResult() { BigDecimal bd1 = new BigDecimal('1.0'); BigDecimal bd2 = new BigDecimal('1.00'); BigDecimal bd3 = new BigDecimal('2.0'); assertTrue(bd1.compareTo(bd3) < 0); assertTrue(bd3.compareTo(bd1) > 0); assertTrue(bd1.compareTo(bd2) == 0); assertTrue(bd1.compareTo(bd3) <= 0); assertTrue(bd1.compareTo(bd2) >= 0); assertTrue(bd1.compareTo(bd3) != 0);}

上面的方法在比較時忽略了小數位。如果你既要比較精度又要比較小數位數那么請使用equals方法:

@Testpublic void whenEqualsCalled_thenSizeAndScaleMatched() { BigDecimal bd1 = new BigDecimal('1.0'); BigDecimal bd2 = new BigDecimal('1.00'); assertFalse(bd1.equals(bd2));}

四則運算

BigDecimal 提供了以下四則運算的方法:

add ——加法 subtract ——減法 divide ——除法,有可能除不盡,必須顯式聲明保留小數位數避免拋出ArithmeticException異常 multiply ——乘法

@Testpublic void whenPerformingArithmetic_thenExpectedResult() { BigDecimal bd1 = new BigDecimal('4.0'); BigDecimal bd2 = new BigDecimal('2.0'); BigDecimal sum = bd1.add(bd2); BigDecimal difference = bd1.subtract(bd2); BigDecimal quotient = bd1.divide(bd2); BigDecimal product = bd1.multiply(bd2); assertTrue(sum.compareTo(new BigDecimal('6.0')) == 0); assertTrue(difference.compareTo(new BigDecimal('2.0')) == 0); assertTrue(quotient.compareTo(new BigDecimal('2.0')) == 0); assertTrue(product.compareTo(new BigDecimal('8.0')) == 0);}

四舍五入

既然是數學運算就不得不講四舍五入。比如我們在金額計算中很容易遇到最終結算金額為人民幣22.355的情況。因為貨幣沒有比分更低的單位所以我們要使用精度和舍入模式規則對數字進行剪裁。java提供有兩個類控制舍入行為RoundingMode和MathContext 。MathContext執行的是IEEE 754R標準目前不太明白其使用場景,我們使用的比較多的是枚舉RoundingMode。它提供了八種模式:

RoundingMode.UP:以小數位為原點 是正數取右邊,負數取左邊RoundingMode.DOWN:以小數位為原點 也就是正數取左邊,負數取右邊RoundingMode.FLOOR:取左邊最近的正數RoundingMode.CEILING:取右邊最近的整數RoundingMode.HALF_DOWN:五舍六入,負數先取絕對值再五舍六入再負數RoundingMode.HALF_UP:四舍五入,負數原理同上RoundingMode.HALF_EVEN:這個比較繞,整數位若是奇數則四舍五入,若是偶數則五舍六入RoundingMode.ROUND_UNNECESSARY:不需要取整,如果存在小數位,就拋ArithmeticException 異常

格式化

數字格式化可通過操作類java.text.NumberFormat和java.text.DecimalFormat提供的api進行操作。其實我們只需要使用java.text.DecimalFormat,因為它代理了NumberFormat。我們來看一下它們的api:

NumberFormat

NumberFormat.getInstance(Locale)、getNumberInstance(Locale)。返回指定語言環境的通用數值格式。NumberFormat.getCurrencyInstance(Locale)。返回指定語言環境的貨幣格式。NumberFormat.getPercentInstance(Locale)。返回指定語言環境的百分比格式。NumberFormat.getIntegerInstance(Locale)。返回指定語言環境的整數數值格式。NumberFormat.setMinimumIntegerDigits(int)。設置數的整數部分所允許的最小位數。NumberFormat.setMaximumIntegerDigits(int)。設置數的整數部分所允許的最大位數。NumberFormat.setMinimumFractionDigits(int)。設置最少小數點位數,不足的位數以0補位,超出的話按實際位數輸出。NumberFormat.setMaximumFractionDigits(int)。設置最多保留小數位數,不足不補0。

DecimalFormat

DecimalFormat除了能代理上面的NumberFormat以外,還提供了基于pattern字符串的格式化風格,有點類似格式化時間一樣。我們來看看pattern的規則:

“0”——表示一位數值,如沒有,顯示0。如“0000.0000”,整數位或小數位>4,按實際輸出,<4整數位前面補0小數位后面補0,湊足4位。 “#”——表示任意位數的整數。如沒有,則不顯示。在小數點位使用,只表示一位小數,超出部分四舍五入。如:“#”:無小數,小數部分四舍五入。“.#”:整數部分不變,一位小數,四舍五入。“.##”:整數部分不變,二位小數,四舍五入。 “.”——表示小數點。注意一個pattern中只能出現一次,超過一次將格式化異常。 “,”——與模式“0”一起使用,表示逗號。注意一定不能在小數點后用,否則格式化異常。

總結

今天對BigDecimal進行了總結歸納,這篇文章建議你收藏備用,也可以轉給其他需要的同學。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持好吧啦網。

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
日韩欧美少妇| 美女视频黄免费的久久| 精品黄色一级片| 麻豆一区二区三区| 卡一卡二国产精品| 精品国产一区二| 精品亚洲成人| 国产精品99一区二区三| 亚洲美女久久精品| 国产在线|日韩| 婷婷综合在线| 中文不卡在线| 伊人久久一区| 国产欧美一区二区三区精品观看| 国产欧美日韩在线一区二区| 麻豆精品视频在线| 久久亚州av| 日韩国产一区| 欧美日韩国产综合网| 免费在线成人网| 国产免费av国片精品草莓男男| 老司机免费视频一区二区三区| 福利视频一区| 亚洲大片在线| 亚洲精品一二| 麻豆国产91在线播放| 性欧美videohd高精| 亚洲一区国产| 久久国内精品| 色偷偷偷在线视频播放| 午夜精品婷婷| 亚洲美女久久| 国产一区二区三区亚洲| 激情久久中文字幕| 亚洲精品欧洲| 国产一区丝袜| 国产亚洲一级| 国产精品sm| 999久久久91| 亚洲精品女人| 国产中文欧美日韩在线| 91精品观看| 日韩精品中文字幕吗一区二区 | 日本精品久久| 97精品国产一区二区三区 | 亚洲精品.com| 香蕉久久久久久| 天堂av在线| 日韩激情一区二区| 国产精品毛片久久| 久久电影一区| 国产在线观看91一区二区三区| 伊人久久亚洲美女图片| 欧美激情麻豆| 亚洲国产一区二区在线观看| 91在线成人| 桃色一区二区| 婷婷成人av| 色婷婷久久久| 69堂免费精品视频在线播放| 青青青免费在线视频| 亚洲v天堂v手机在线| 欧产日产国产精品视频| 亚洲免费专区| 欧美va亚洲va日韩∨a综合色| 国产一区 二区| 欧美天堂亚洲电影院在线观看| 欧美交a欧美精品喷水| 香蕉久久国产| 亚洲播播91| 国产精品传媒麻豆hd| 国产视频欧美| 久久精品国产免费| 日韩综合一区二区三区| 久久国产精品成人免费观看的软件| 国产欧美另类| 国产亚洲精品久久久久婷婷瑜伽| 97精品一区| 久久av国产紧身裤| 亚洲精品成人一区| 日韩午夜免费| 亚洲91精品| 水蜜桃久久夜色精品一区| 日韩高清一区在线| 亚洲一区亚洲| 91精品久久久久久久久久不卡| 国产精品片aa在线观看| 中文精品视频| 亚洲午夜电影| 蜜桃精品在线| 日本一二区不卡| 国产伦精品一区二区三区千人斩 | 久久亚洲精精品中文字幕| 日韩av一区二区在线影视| 亚洲免费影视| 欧美日韩精品免费观看视频完整| 欧美天堂视频| 成人福利av| 久久久久免费| 久久99蜜桃| 国产乱码精品一区二区三区亚洲人 | 欧美视频二区| 日韩三级一区| 亚洲无线观看| 鲁大师成人一区二区三区| 狠狠色狠狠色综合日日tαg| 九九色在线视频| 亚洲精品一区三区三区在线观看| 粉嫩av一区二区三区四区五区 | 国产精品亚洲欧美| 九九精品调教| 成人午夜国产| 亚洲视频综合| 最新国产拍偷乱拍精品| 欧美 日韩 国产一区二区在线视频| 性欧美videohd高精| 久久久久一区| 亚洲调教视频在线观看| 激情综合网站| 久久精品播放| 欧洲激情综合| 国产精品试看| 另类激情亚洲| 亚洲一区有码| 日韩精品视频中文字幕| 久久精品xxxxx| 国产精品色在线网站| 麻豆中文一区二区| 9999国产精品| 久久亚洲国产| 99国产精品99久久久久久粉嫩| 日韩中文字幕91| 日本亚洲欧洲无免费码在线| 日韩成人精品一区二区三区 | 日韩一区二区三区高清在线观看| 亚久久调教视频| 日本少妇精品亚洲第一区| 久久国产乱子精品免费女| 久久免费福利| 久久国产免费| 国产亚洲欧洲| 国产日韩高清一区二区三区在线 | 欧美在线影院| 亚洲精品大全| 国产精品分类| 国产超碰精品| 香蕉成人久久| 国产精品综合色区在线观看| 麻豆一区二区三| 久久久久国产| 亚洲精品欧美| 成人日韩av| 午夜视频精品| 日韩国产欧美在线视频| 精品久久久久久久| 国产一区日韩一区| 深夜日韩欧美| 国产+成+人+亚洲欧洲在线| 欧美亚洲国产一区| 亚洲bt欧美bt精品777| 美女av一区| 国产综合欧美| 日韩欧美久久| www.com.cn成人| 亚洲精品乱码日韩| 精品视频91| 黄色av一区| 国产精品一区二区99| 久久久国产亚洲精品| 日韩三区四区| 日韩电影免费网站| 亚洲aa在线| 日韩高清中文字幕一区二区| 蜜桃视频一区二区三区| 久久三级中文| 99视频一区| 欧美日韩亚洲一区二区三区在线| 色爱综合网欧美| 亚洲午夜国产成人| 日韩国产一区二区三区| 亚洲18在线| 久久精品1区| 国产欧美二区| 欧美女激情福利| 精品欠久久久中文字幕加勒比| 在线视频精品| 国产不卡一区| 日韩精品免费观看视频| 精品免费av在线| 国产免费av国片精品草莓男男| 午夜av一区| 国产在线一区不卡| 婷婷综合国产| 免费欧美一区| 国产中文欧美日韩在线| 中文字幕日韩欧美精品高清在线| 国产成人久久精品麻豆二区 | 国产精品一区二区三区美女| 亚州av乱码久久精品蜜桃| 国产精品1区|