摘要:舍入方式需要弄明白自己的業(yè)務(wù)才用,別為了用而隨便選一個用四舍五入模式從零四舍五入。原值結(jié)論都是向前進一位四舍五入到正無窮。
一:相除精度丟失的問題
BigDecimal的api除法相對加減乘要實現(xiàn)的復(fù)雜多了,只介紹常用的我遇到的問題:
問題:兩數(shù)相除,如果9/3=3整除沒問題,但是10/3=0.33333333......除不盡,這里不能讓電腦一直除不盡,所以BigDecimal做出一些限制;
必須按照(數(shù),保留小數(shù)位(最好要合理限制最大精度),舍入方式)來操作
否則就會拋出異常,例如:
public static void main(String[] args) {
BigDecimal a = new BigDecimal(10); BigDecimal b = new BigDecimal(3); BigDecimal c = a.divide(b); }
執(zhí)行:拋出
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
at java.math.BigDecimal.divide(BigDecimal.java:1616)
二:舍入方式精度丟失的問題
多數(shù)相乘時,請勿先進行四舍五入或者其他的方式,以最終計算結(jié)果為基礎(chǔ)進行取舍精度,雖然一說就明白,但是這一個編碼的習(xí)慣問題,特別是在金融行業(yè)。
舍入方式需要弄明白自己的業(yè)務(wù)才用,別為了用而隨便選一個用
1.ROUND_UP:四舍五入模式從零四舍五入。
main(String[] args) {
BigDecimal a = BigDecimal(0.31); BigDecimal b = BigDecimal(3); BigDecimal c = a.divide(b,1,BigDecimal.ROUND_UP); LOGGER.error("原值:0.1033333...///"+c.toString()+"=0.2"); //結(jié)論:0-9都是向前進一位(且當(dāng)0后還有小數(shù)位為前提)
}
2.ROUND_DOWN 四舍五入模式到四舍五入接近零。
main(String[] args) {
BigDecimal a = BigDecimal(0.39); BigDecimal b = BigDecimal(1); BigDecimal c = a.divide(b,1,BigDecimal.ROUND_DOWN); LOGGER.error("原值:0.39///"+c.toString()+"=0.3");
//結(jié)論:1-9都是向前進一位
}
3.ROUND_CEILING 四舍五入到正無窮。
public static void main(String[] args) {
BigDecimal a = new BigDecimal(0.301); BigDecimal b = new BigDecimal(1); BigDecimal c = a.divide(b,1,BigDecimal.ROUND_CEILING); LOGGER.error("原值:0.301///"+c.toString()+"=0.4");
//結(jié)論:與第一種類似,區(qū)別就是舍入到正無窮的范圍大,當(dāng)值為負數(shù)時舍入失效,當(dāng)用第四種解決
}
4.ROUND_FLOOR 四舍五入到負無窮
main(String[] args) {
BigDecimal a = BigDecimal(-0.301); BigDecimal b = BigDecimal(1); BigDecimal c = a.divide(b,1,BigDecimal.ROUND_FLOOR); LOGGER.error("原值:0.301///"+c.toString()+"=0.4");
//結(jié)論:與上面的正無窮舍入的方式相反,可以互補
}
5.ROUND_HALF_UP 四舍五入方式四舍五入,除非兩個鄰邊距離相等,則四舍五入。
public static void main(String[] args) {
BigDecimal a = new BigDecimal(-0.36); BigDecimal b = new BigDecimal(1); BigDecimal c = a.divide(b,1,BigDecimal.ROUND_HALF_UP); LOGGER.error("原值:-0.36///"+c.toString()+"=-0.4"); //結(jié)論:正負數(shù)相同,以5為分界,<=5舍掉,>5的進1 }
6.ROUND_HALF_DOWN 四舍五入模式四舍五入,除非兩個鄰邊距離相等
public static void main(String[] args) {
BigDecimal a = new BigDecimal(-0.35); BigDecimal b = new BigDecimal(1); BigDecimal c = a.divide(b,1,BigDecimal.ROUND_HALF_DOWN ); LOGGER.error("原值:-0.35///"+c.toString()+"=-0.3"); //結(jié)論:正負數(shù)相同,以5為分界,<=5舍掉,>5的進1 }
7.ROUND_HALF_EVEN 四舍五入的方式是四舍五入,除非兩個鄰邊是等距的,在這種情況下,四舍五入對甚至鄰居。
public static void main(String[] args) {
BigDecimal a = new BigDecimal(-0.35); BigDecimal b = new BigDecimal(1); BigDecimal c = a.divide(b,1,BigDecimal.ROUND_HALF_EVEN ); LOGGER.error("原值:-0.35///"+c.toString()+"=-0.3"); //結(jié)論:正負數(shù)相同,以5為分界,<=5舍掉,>5的進1 }
8.ROUND_UNNECESSARY 舍入模式,以斷言所請求的操作具有精確值結(jié)果,因此不需要舍入。
public static void main(String[] args) {
BigDecimal a = new BigDecimal(-0.36); BigDecimal b = new BigDecimal(1); BigDecimal c = a.divide(b,1,BigDecimal.ROUND_HALF_EVEN ); LOGGER.error("原值:-0.36///"+c.toString()+"=-0.4"); //結(jié)論:正負數(shù)相同,以5為分界,<=5舍掉,>5的進1 // 斷言中使用的,實際開發(fā)過程中最好不用 }
三:BigDecimal取值范圍的 validation 校驗問題總結(jié)
常常在與客戶端交互時需要做很多校驗,在javax.validation下面有很多不錯的校驗規(guī)則
@NotNull :不為空,適用任何地方(@NotBlank只是用字符類型)
@DecimalMax:取得最大值范圍
@DecimalMin(value = "0.00", message = "") 取值最小值
三:BigDecimal精度科學(xué)計數(shù)法問題總結(jié)
BigDecimal有一種方法是:stripTrailingZeros(),它提供了去掉小數(shù)點后面的多余的0,但是問題是:
public static void main(String[] args) { BigDecimal A = BigDecimal.valueOf(0.36000).stripTrailingZeros(); BigDecimal B = new BigDecimal(0.36000).stripTrailingZeros(); BigDecimal zeroDecimal = new BigDecimal(0.000).stripTrailingZeros(); System.out.println("原值0.36000//////"+A.toPlainString()+"===0.36"); System.out.println("原值0.36000//////"+B.toPlainString()+"===35999999999999998667732370449812151491641998291015625"); System.out.println("原值0.00000//////"+zeroDecimal+"==0.0000////"+zeroDecimal.toPlainString()+"==0"); }
①:導(dǎo)出是excel會以科學(xué)計數(shù)法展示數(shù)據(jù),如120 -》1.2+E2;
②:如果0.000然后用stripTrailingZeros()是無效的,導(dǎo)出時toPlainString()加上之后就可以了;
③:慎用new BigDecimal();源代碼如下;
/**這個構(gòu)造函數(shù)的結(jié)果可能有些不可預(yù)測。
*可能會假設(shè)編寫{@code new BigDecimal(0.1)}
Java創(chuàng)建一個完全等于的{@code BigDecimal}
0.1(未縮放值為1,刻度為1),但它是
實際上等于 0.1000000000000000055511151231257827021181583404541015*625.
**/public BigDecimal(double val) {
this(val,MathContext.UNLIMITED);
}
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/73440.html
摘要:除法的精度問題在使用的除法時,遇到一個鬼畜的問題,本以為的精度計算,結(jié)果使用返回,當(dāng)然最終發(fā)現(xiàn)還是自己的使用姿勢不對導(dǎo)致的,因此記錄一下,避免后面重蹈覆轍問題拋出在使用做高精度的除法時,一不注意遇到了一個小問題,如下上面的輸出是什么 showImg(https://segmentfault.com/img/remote/1460000015555232); BigDecimal除法的精...
摘要:策略策略,指的是可以實現(xiàn)目標(biāo)的方案集合,在某些特定情況下,策略之間是可以相互替換的。如何計算金額我們先拿點外賣中會員折扣活動舉例子來說明一下吧。這就是策略模式。策略模式提供了管理相關(guān)的算法族的辦法。showImg(https://user-gold-cdn.xitu.io/2019/5/13/16aaf673fde1b546);?周末無事,窩在家里面看《權(quán)力的游戲第八季》,看的很是津津有味,...
摘要:若要擴展功能,裝飾者提供了比繼承更有彈性的替代方案。裝飾者模式意味著一群裝飾者類,這些類用來包裝具體組件。裝飾者類反映出被裝飾組件類型。裝飾者會導(dǎo)致設(shè)計中出現(xiàn)許多小對象,如果過度使用,會讓程序變得很復(fù)雜。 嘿嘿嘿,你是不是很喜歡用繼承呢?感覺沒什么事情是一個爸爸類搞不定的,有的話就兩個,快來跟我看看這個模式吧,它能讓你斷奶,給愛用繼承的人一個全新的設(shè)計眼界。 直奔主題,你是否有聽說...
摘要:項目環(huán)境用于發(fā)送請求測試項目介紹這是一個商城項目,本來想起名叫項目,發(fā)現(xiàn)自己并沒有用。也是自己第一篇博客,記錄一下自己的學(xué)習(xí)過程,希望一方面能多做寫項目鍛煉能力,另一方面也讓自己在做完之后寫寫博客自己總結(jié)反思。 1.項目環(huán)境 IDEA15 spring4 mybatis3.4 mysql RestLet Client用于發(fā)送請求測試 2.項目介紹 這是一個商城項目,本來想起名叫SSM項...
摘要:支付流程以上是微信支付的流程用戶進入選擇商品進行購買,在內(nèi)部結(jié)算時生成用戶本系統(tǒng)訂單待支付狀態(tài),此時返回訂單信息與支付方式列表用戶確認(rèn)金額無誤,并選擇支付方式。 支付流程 showImg(https://segmentfault.com/img/bVytNT?w=894&h=1042); 以上是微信app支付的流程: 用戶進入app選擇商品進行購買,在app內(nèi)部結(jié)算時生成用戶本系統(tǒng)訂...
閱讀 1682·2019-08-30 15:54
閱讀 3332·2019-08-26 17:15
閱讀 3522·2019-08-26 13:49
閱讀 2582·2019-08-26 13:38
閱讀 2291·2019-08-26 12:08
閱讀 3035·2019-08-26 10:41
閱讀 1369·2019-08-26 10:24
閱讀 3376·2019-08-23 18:35