BigDecimal經過setScale設置小數位數發生ArithmeticException

1、前言java

一般進行數值計算時,咱們會先將double或float等轉爲BigDecimal再處理,而後對計算結果經過setScale方法取指定的小數位;可是在這裏有時會遇到java.lang.ArithmeticException: Rounding necessary,下面咱們會對此問題進行演示和說明。spa

2、代碼示例code

1. 這裏以double轉BigDecimal後獲取不一樣小數位值來舉例說明,具體以下:ci

public static void main(String[] args) {

      double d = 10.0000000001;

      String s = "10.0000000001";

      BigDecimal newBigDecimal = new BigDecimal(d);

      BigDecimal newStringBigDecimal = new BigDecimal(s);

      BigDecimal valueOfBigDecimal = BigDecimal.valueOf(d);

      // newBigDecimal===================================

      System.out.println("newBigDecimal's scale:" + newBigDecimal.scale());

      try {

         System.out.println("newBigDecimal setScale(50):" + newBigDecimal.setScale(50));

      } catch (Exception e) {

         System.out.println("newBigDecimal setScale(50):" + e);

      }

      try {

         System.out.println("newBigDecimal setScale(49):" + newBigDecimal.setScale(49));

      } catch (Exception e) {

         System.out.println("newBigDecimal setScale(49):" + e);

      }

      try {

         System.out.println("newBigDecimal setScale(48):" + newBigDecimal.setScale(48));

      } catch (Exception e) {

         System.out.println("newBigDecimal setScale(48):" + e);

         System.out.println("newBigDecimal setScale(48, RoundingMode.HALF_UP):" + newBigDecimal.setScale(48, RoundingMode.HALF_UP));

      }

       

      // valueOfBigDecimal======================================

      System.out.println("valueOfBigDecimal's scale:" + valueOfBigDecimal.scale());

      try {

         System.out.println("valueOfBigDecimal setScale(50):" + valueOfBigDecimal.setScale(50));

      } catch (Exception e) {

         System.out.println("valueOfBigDecimal setScale(50):" + e);

      }

      try {

         System.out.println("valueOfBigDecimal setScale(49):" + valueOfBigDecimal.setScale(49));

      } catch (Exception e) {

         System.out.println("valueOfBigDecimal setScale(49):" + e);

      }

      try {

         System.out.println("valueOfBigDecimal setScale(48):" + valueOfBigDecimal.setScale(48));

      } catch (Exception e) {

         System.out.println("valueOfBigDecimal setScale(48):" + e);

         System.out.println("valueOfBigDecimal setScale(48, RoundingMode.HALF_UP):" + valueOfBigDecimal.setScale(48, RoundingMode.HALF_UP));

      }

      // newStringBigDecimal======================================

      System.out.println("newStringBigDecimal's scale:" + newStringBigDecimal.scale());

      try {

         System.out.println("newStringBigDecimal setScale(50):" + newStringBigDecimal.setScale(50));

      } catch (Exception e) {

         System.out.println("newStringBigDecimal setScale(50):" + e);

      }

      try {

         System.out.println("newStringBigDecimal setScale(49):" + newStringBigDecimal.setScale(49));

      } catch (Exception e) {

         System.out.println("newStringBigDecimal setScale(49):" + e);

      }

      try {

         System.out.println("newStringBigDecimal setScale(48):" + newStringBigDecimal.setScale(48));

      } catch (Exception e) {

         System.out.println("newStringBigDecimal setScale(48):" + e);

         System.out.println("newStringBigDecimal setScale(48, RoundingMode.HALF_UP):" + newStringBigDecimal.setScale(48, RoundingMode.HALF_UP));

      }

       

      d = 10.01;

      s = "10.01";

      newBigDecimal = new BigDecimal(d);

      valueOfBigDecimal = BigDecimal.valueOf(d);

      newStringBigDecimal = new BigDecimal(s);

      // newBigDecimal==========================================

      System.out.println("newBigDecimal's scale:" + newBigDecimal.scale());

      try {

         System.out.println("newBigDecimal setScale(3):" + newBigDecimal.setScale(3));

      } catch (Exception e) {

         System.out.println("newBigDecimal setScale(3):" + e);

         System.out.println("newBigDecimal setScale(3, RoundingMode.HALF_UP):" + newBigDecimal.setScale(3, RoundingMode.HALF_UP));

      }

      try {

         System.out.println("newBigDecimal setScale(2):" + newBigDecimal.setScale(2));

      } catch (Exception e) {

         System.out.println("newBigDecimal setScale(2):" + e);

         System.out.println("newBigDecimal setScale(2, RoundingMode.HALF_UP):" + newBigDecimal.setScale(2, RoundingMode.HALF_UP));

      }

      try {

         System.out.println("newBigDecimal setScale(1):" + newBigDecimal.setScale(1));

      } catch (Exception e) {

         System.out.println("newBigDecimal setScale(1):" + e);

         System.out.println("newBigDecimal setScale(1, RoundingMode.HALF_UP):" + newBigDecimal.setScale(1, RoundingMode.HALF_UP));

      }

       

      // valueOfBigDecimal======================================

      System.out.println("valueOfBigDecimal's scale:" + valueOfBigDecimal.scale());

      try {

         System.out.println("valueOfBigDecimal setScale(3):" + valueOfBigDecimal.setScale(3));

      } catch (Exception e) {

         System.out.println("valueOfBigDecimal setScale(3):" + e);

      }

      try {

         System.out.println("valueOfBigDecimal setScale(2):" + valueOfBigDecimal.setScale(2));

      } catch (Exception e) {

         System.out.println("valueOfBigDecimal setScale(2):" + e);

      }

      try {

         System.out.println("valueOfBigDecimal setScale(1):" + valueOfBigDecimal.setScale(1));

      } catch (Exception e) {

         System.out.println("valueOfBigDecimal setScale(1):" + e);

         System.out.println("valueOfBigDecimal setScale(1, RoundingMode.HALF_UP):" + valueOfBigDecimal.setScale(1, RoundingMode.HALF_UP));

      }

      // 

      // newStringBigDecimal======================================

      System.out.println("newStringBigDecimal's scale:" + newStringBigDecimal.scale());

      try {

         System.out.println("newStringBigDecimal setScale(3):" + newStringBigDecimal.setScale(3));

      } catch (Exception e) {

         System.out.println("newStringBigDecimal setScale(3):" + e);

      }

      try {

         System.out.println("newStringBigDecimal setScale(2):" + newStringBigDecimal.setScale(2));

      } catch (Exception e) {

         System.out.println("newStringBigDecimal setScale(2):" + e);

      }

      try {

         System.out.println("newStringBigDecimal setScale(1):" + newStringBigDecimal.setScale(1));

      } catch (Exception e) {

         System.out.println("newStringBigDecimal setScale(1):" + e);

         System.out.println("newStringBigDecimal setScale(1, RoundingMode.HALF_UP):" + newStringBigDecimal.setScale(1, RoundingMode.HALF_UP));

      }

   }

運算結果以下:文檔

newBigDecimal's scale:49

newBigDecimal setScale(50):10.00000000010000000827403709990903735160827636718750

newBigDecimal setScale(49):10.0000000001000000082740370999090373516082763671875

newBigDecimal setScale(48):java.lang.ArithmeticException: Rounding necessary

newBigDecimal setScale(48, RoundingMode.HALF_UP):10.000000000100000008274037099909037351608276367188

valueOfBigDecimal's scale:10

valueOfBigDecimal setScale(50):10.00000000010000000000000000000000000000000000000000

valueOfBigDecimal setScale(49):10.0000000001000000000000000000000000000000000000000

valueOfBigDecimal setScale(48):10.000000000100000000000000000000000000000000000000

newStringBigDecimal's scale:10

newStringBigDecimal setScale(50):10.00000000010000000000000000000000000000000000000000

newStringBigDecimal setScale(49):10.0000000001000000000000000000000000000000000000000

newStringBigDecimal setScale(48):10.000000000100000000000000000000000000000000000000

newBigDecimal's scale:49

newBigDecimal's value:10.0099999999999997868371792719699442386627197265625

newBigDecimal setScale(3):java.lang.ArithmeticException: Rounding necessary

newBigDecimal setScale(3, RoundingMode.HALF_UP):10.010

newBigDecimal setScale(2):java.lang.ArithmeticException: Rounding necessary

newBigDecimal setScale(2, RoundingMode.HALF_UP):10.01

newBigDecimal setScale(1):java.lang.ArithmeticException: Rounding necessary

newBigDecimal setScale(1, RoundingMode.HALF_UP):10.0

valueOfBigDecimal's scale:2

valueOfBigDecimal setScale(3):10.010

valueOfBigDecimal setScale(2):10.01

valueOfBigDecimal setScale(1):java.lang.ArithmeticException: Rounding necessary

valueOfBigDecimal setScale(1, RoundingMode.HALF_UP):10.0

newStringBigDecimal's scale:2

newStringBigDecimal setScale(3):10.010

newStringBigDecimal setScale(2):10.01

newStringBigDecimal setScale(1):java.lang.ArithmeticException: Rounding necessary

newStringBigDecimal setScale(1, RoundingMode.HALF_UP):10.0

2. 結果分析:string

經過運行結果咱們會發現兩種狀況:it

①經過new直接將double做爲參數傳入獲得的值輸出後並不等於原double值,傳入string或valueOf方法獲得的結果等於原值;io

事實上查看Java文檔會發現有三種方式將double轉爲BigDecimal:二進制

1. new BigDecimal(double d);float

2. new BigDecimal(String s);

3.BigDecimal.valueOf(double d) ;

第一種是double的二進制形式的結果,因此BigDecimal的值並不必定爲其原值,如上代碼所示:10.0000000001轉換後爲10.0000000001000000082740370999090373516082763671875 ,

共有49位小數(不一樣機器結果會不一樣),

10.01轉換後爲10.0099999999999997868371792719699442386627197265625,

第二種和第三種結果相同,仍然爲原值,由於第三種至關於先將double轉爲String(Double.toString(double))。

②同時咱們會發現,當設置結果小數位數小於當前位數時,若是未設置進位方式會拋出異常:java.lang.ArithmeticException: Rounding necessary,提示咱們進位方式必須,當咱們設置四捨五入後便可,其餘方式可查看RoundingMode枚舉類。

3、結論:

經過上述分析,咱們能夠看出當對BigDecimal的值進位時需指定進位方式,不然會發生java.lang.ArithmeticException: Rounding necessary。

相關文章
相關標籤/搜索