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