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