天天看點

BigDecimal 小數 浮點數 精度 财務計算

float和double類型的使用局限:

單精度浮點型變量float可以處理6~7位有效數,雙精度浮點型變量double可以處理15~16位有效數,在實際應用中,如果需要對更大或者更小的數進行運算和處理,這時候float和double就如能為力了。

借用《Effactive Java》這本書中的話,float和double類型的主要設計目标是為了科學計算和工程計算,他們執行二進制浮點運算,這是為了在廣域數值範圍上提供較為精确的快速近似計算而精心設計的。然而,它們沒有提供完全精确的結果,是以不應該被用于要求精确結果的場合。但是,商業計算往往要求結果精确,這時候BigDecimal就派上大用場啦。

BigDecimal

BigDecimal用來對超過16位有效位的數進行精确的運算。BigDecimal所建立的是對象,我們不能使用傳統的+、-、*、/等算術運算符直接對其對象進行數學運算,而必須調用其相對應的方法。方法中的參數也必須是BigDecimal的對象。

BigDecimal 由【任意精度的整數非标度值】和【32 位的整數标度 (scale)】組成。如果為零或正數,則标度是小數點後的位數;如果為負數,則将該數的非标度值乘以 10 的負scale 次幂。是以,BigDecimal表示的數值是【unscaledValue * 10^-scale】。

JDK中對BigDecimal的定義為:不可變的、任意精度的有符号十進制數。

BigDecimal 類提供以下操作:算術、标度操作、舍入、比較、雜湊演算法和格式轉換。toString() 方法提供 BigDecimal 的規範表示形式。

注意,BigDecimal對象是不可變的(immutable)的(像String、BigInteger一樣),我們在調用其加減乘除等方法後,其實最終都傳回的是一個新的BigDecimal對象,是以在做每一步運算時一定要儲存操作後的值。

該對象是封裝上下文設定的不可變對象,它描述數字運算符的某些規則,例如由 BigDecimal 類實作的規則。

基本獨立設定為:

precision:某個操作使用的數字個數;結果舍入到此精度

roundingMode:一個 RoundingMode 對象,該對象指定舍入使用的算法。

構造方法

MathContext(int setPrecision)  構造一個新的 MathContext,它具有指定的精度和 HALF_UP 舍入模式。 參數setPrecision為非負 int 精度設定。

MathContext(int setPrecision, RoundingMode setRoundingMode)  構造一個新的 MathContext,它具有指定的精度和舍入模式。

MathContext(String val)  根據字元串構造一個新的 MathContext。該字元串的格式必須與 toString() 方法生成的字元串的格式相同。

靜态字段

static MathContext  DECIMAL128:一個 MathContext 對象,其精度設定與 IEEE 754R Decimal128 格式(即 34 個數字)比對,舍入模式為 HALF_EVEN,這是 IEEE 754R 的預設舍入模式。

static MathContext  DECIMAL32 : 一個 MathContext 對象,其精度設定與 IEEE 754R Decimal32 格式(即 7 個數字)比對,舍入模式為 HALF_EVEN,這是 IEEE 754R 的預設舍入模式。

static MathContext  DECIMAL64 : 一個 MathContext 對象,其精度設定與 IEEE 754R Decimal64 格式(即 16 個數字)比對,舍入模式為 HALF_EVEN,這是 IEEE 754R 的預設舍入模式。

static MathContext  UNLIMITED : 其設定具有無限精度算法所需值的 MathContext 對象。該設定的值為: precision=0,roundingMode=HALF_UP

PS:預設的HALF_EVEN模式不是"四舍五入"的模式,我們最好改為HALF_UP模式。

公共方法

int  getPrecision()  傳回 precision 設定。此值始終為非負數。

RoundingMode  getRoundingMode()  傳回 roundingMode 設定。它将是8種RoundingMode之一。

boolean  equals(Object x)  将此 MathContext 與指定的 Object 進行相等性比較。

int  hashCode()  傳回此 MathContext 的哈希碼。

String  toString()  傳回此 MathContext 的字元串表示形式。

BigDecimal(BigInteger val)  将 BigInteger 轉換為 BigDecimal。

BigDecimal(BigInteger unscaledVal, int scale)  将 BigInteger 非标度值和 int 标度轉換為 BigDecimal。

【帶MathContext參數--根據上下文設定進行舍入】

BigDecimal(BigInteger val, MathContext mc) 

BigDecimal(BigInteger unscaledVal, int scale, MathContext mc)

BigDecimal(char[] in)  将 BigDecimal 的字元數組表示形式轉換為 BigDecimal,接受與 BigDecimal(String) 構造方法相同的字元序列。

BigDecimal(char[] in, int offset, int len)  将 BigDecimal 的字元數組表示形式轉換為 BigDecimal,接受與 BigDecimal(String) 構造方法相同的字元序列,同時允許指定子數組。

BigDecimal(char[] in, MathContext mc)

BigDecimal(char[] in, int offset, int len, MathContext mc)

BigDecimal(double val)  将 double 轉換為 BigDecimal,後者是 double 的二進制浮點值準确的十進制表示形式。

BigDecimal(int val)  将 int 轉換為 BigDecimal。

BigDecimal(long val)  将 long 轉換為 BigDecimal。

BigDecimal(String val)  将 BigDecimal 的字元串表示形式轉換為 BigDecimal。

BigDecimal(double val, MathContext mc)

BigDecimal(int val, MathContext mc)

BigDecimal(long val, MathContext mc)

BigDecimal(String val, MathContext mc)

1、不推薦使用含有double的構造方法

參數類型為double的構造方法的結果有一定的不可預知性。有人可能認為在Java中寫入new BigDecimal(0.1)所建立的BigDecimal正好等于 0.1(非标度值 1,其标度為 1,即 1*10^-1),但是它實際上等于***。這是因為0.1無法準确地表示為 double(或者說對于該情況,不能表示為任何有限長度的二進制小數)。這樣,傳入到構造方法的值不會正好等于 0.1(雖然表面上等于該值)。

​<code>​System.out.println(new BigDecimal(1.22) + " " + new BigDecimal("1.22"));//1.2199999999999999733546474089962430298328399658203125 1.22​</code>​​<code>​System.out.println(new BigDecimal(1.22).doubleValue() == new BigDecimal("1.22").doubleValue());//true,并且都 == 1.22​</code>​

2、當 double 必須用作 BigDecimal 的源時,可使用下面兩種方式之一:

先使用 Double.toString 方法将 double 轉換為 String,然後使用含有 String 的構造方法。

含有 String 的構造方法是完全可預知的:寫入 new BigDecimal("0.1") 将建立一個 BigDecimal,它正好等于預期的 0.1。是以,比較而言,通常建議優先使用含有 String 的構造方法。

也直接使用BigDecimal類中靜态的valueOf方法,這通常是将 double 和 float 轉換為一個 BigDecimal 的最好方式(第一種方式從本質上将也是采用的這種方式)

三個執行個體

static BigDecimal  ONE  值為 1,标度為 0。

static BigDecimal  TEN  值為 10,标度為 0。

static BigDecimal  ZERO  值為 0,标度為 0。  

以下模式和RoundingMode中定義的模式是完全一緻的,且JDK中建議使用RoundingMode中定義的模式。具體詳見另一篇筆記。

static int  ROUND_CEILING(天花闆; 最高限度)  接近正無窮大的舍入模式。

static int  ROUND_DOWN  接近零的舍入模式。

static int  ROUND_FLOOR  接近負無窮大的舍入模式。

static int  ROUND_UP  舍入遠離零的舍入模式。

static int  ROUND_UNNECESSARY  斷言請求的操作具有精确的結果,是以不需要舍入。

static int  ROUND_HALF_DOWN  向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則為上舍入的舍入模式。

static int  ROUND_HALF_EVEN  向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則向相鄰的偶數舍入。

static int  ROUND_HALF_UP  向“最接近的”數字舍入,如果與兩個相鄰數字的距離相等,則為向上舍入的舍入模式。

static BigDecimal  valueOf(double val)  傳回值和 new BigDecimal(Double.toString(val)) 完全一緻。

static BigDecimal  valueOf(long val)  将 long 值轉換為具有零标度的 BigDecimal。

static BigDecimal  valueOf(long unscaledVal, int scale)  将 long 非标度值和 int 标度轉換為 BigDecimal。

【擷取标度、精度、正負号】

int  precision()  傳回此 BigDecimal 的精度(精度是非标度值的數字【個數】)。零值的精度是 1。

int  scale()  傳回此 BigDecimal 的标度。如果為零或正數,則标度是小數點後的位數。如果為負數,則将該數的非标度值乘以 10 的負 scale 次幂。例如, -3 标度是指非标度值乘以 1000。

int  signum()  傳回此 BigDecimal 的正負号函數。當此 BigDecimal 的值為負、零或正時,傳回 -1、0 或 1。

【設定标度】

BigDecimal  setScale(int newScale)  傳回一個 BigDecimal,其标度為指定值,其值在數值上等于此 BigDecimal 的值。如果這不可能,則抛出 ArithmeticException。

BigDecimal  setScale(int newScale, int roundingMode)  傳回一個 BigDecimal,其标度為指定值,其非标度值通過此 BigDecimal 的非标度值乘以或除以十的适當次幂來确定,以維護其總值。相對于此遺留方法,應優先使用新的 setScale(int, RoundingMode) 方法。

BigDecimal  setScale(int newScale, RoundingMode roundingMode)  傳回 BigDecimal,其标度為指定值,其非标度值通過此 BigDecimal 的非标度值乘以或除以十的适當次幂來确定,以維護其總值。

BigDecimal  add(BigDecimal augend)  傳回一個 BigDecimal,其值為 (this + augend),其标度為 max(this.scale(), augend.scale())。

BigDecimal  subtract(BigDecimal subtrahend)  傳回一個 BigDecimal,其值為 (this - subtrahend),其标度為 max(this.scale(), subtrahend.scale())。

BigDecimal  multiply(BigDecimal multiplicand)  傳回一個 BigDecimal,其值為 (this multiplicand),其标度為 (this.scale() + multiplicand.scale())。

BigDecimal  divide(BigDecimal divisor)  傳回一個 BigDecimal,其值為 (this / divisor),其首選标度為 (this.scale() - divisor.scale());如果無法表示準确的商值(因為它有無窮的十進制擴充),則抛出 ArithmeticException。

BigDecimal  pow(int n)  傳回其值為 (this^n) 的 BigDecimal,準确計算該幂,使其具有無限精度。參數 n 必須在 0 到 999999999(包括)之間。ZERO.pow(0) 傳回 ONE。 注意,未來版本可能會擴充此方法允許的指數範圍。

BigDecimal  scaleByPowerOfTen(int n)  傳回其數值等于 (this * 10^n) 的 BigDecimal。該結果的标度為 (this.scale() - n)。

BigDecimal  add(BigDecimal augend, MathContext mc)

BigDecimal  subtract(BigDecimal subtrahend, MathContext mc)

BigDecimal  multiply(BigDecimal multiplicand, MathContext mc)

BigDecimal  divide(BigDecimal divisor, MathContext mc)  傳回其值為 (this / divisor) 的 BigDecimal(根據上下文設定進行舍入)。

BigDecimal  pow(int n, MathContext mc)  傳回其值為 (thisn) 的 BigDecimal。

【除法擴充_為除法指定舍入模式】

BigDecimal  divide(BigDecimal divisor, int roundingMode)  傳回一個 BigDecimal,其值為 (this / divisor),其标度為 this.scale()。如果必須執行舍入,以生成具有給定标度的結果,則應用指定的舍入模式。相對于此遺留方法,應優先使用新的 divide(BigDecimal, RoundingMode) 方法。

BigDecimal  divide(BigDecimal divisor, RoundingMode roundingMode)  傳回一個 BigDecimal,其值為 (this / divisor),其标度為 this.scale()。如果必須執行舍入,以生成具有給定标度的結果,則應用指定的舍入模式。

【除法擴充_為除法指定标度和舍入模式】

BigDecimal  divide(BigDecimal divisor, int scale, int roundingMode)  傳回一個 BigDecimal,其值為 (this / divisor),其标度為指定标度。如果必須執行舍入,以生成具有指定标度的結果,則應用指定的舍入模式。相對于此遺留方法,應優先使用新的 divide(BigDecimal, int, RoundingMode) 方法。

BigDecimal  divide(BigDecimal divisor, int scale, RoundingMode roundingMode)  傳回一個 BigDecimal,其值為 (this / divisor),其标度為指定标度。如果必須執行舍入,以生成具有指定标度的結果,則應用指定的舍入模式。

BigDecimal  divideToIntegralValue(BigDecimal divisor)  傳回 BigDecimal,其值為向下舍入所得商值(this / divisor)的整數部分。該結果的首選标度為(this.scale() - divisor.scale())。

BigDecimal  remainder(BigDecimal divisor)  傳回其值為 (this % divisor) 的 BigDecimal。餘數由 this.subtract( this.divideToIntegralValue(divisor) .multiply(divisor) ) 給出。注意,這不是模操作(結果可以為負)。

BigDecimal[]  divideAndRemainder(BigDecimal divisor)  傳回由兩個元素組成的 BigDecimal 數組,該數組包含 divideToIntegralValue 的結果,後跟對兩個操作數計算所得到的 remainder。注意,如果同時需要整數商和餘數,則此方法比分别使用 divideToIntegralValue 和 remainder 方法更快速,因為相除僅需執行一次。

【帶MathContext參數】

BigDecimal  remainder(BigDecimal divisor, MathContext mc)

BigDecimal  divideToIntegralValue(BigDecimal divisor, MathContext mc)

BigDecimal[]  divideAndRemainder(BigDecimal divisor, MathContext mc)

​<code>​ ​</code>​

​<code>​BigDecimal bd_div = bd1.divide(bd2);//商​</code>​​<code>​BigDecimal bd_dti = bd1.divideToIntegralValue(bd2);//向下舍入所得商值(this / divisor)的整數部分​</code>​​<code>​BigDecimal bd_tem = bd1.subtract(bd1.divideToIntegralValue(bd2).multiply(bd2));//remainder計算的過程​</code>​​<code>​BigDecimal bd_rem = bd1.remainder(bd2);//傳回其值為 (this % divisor) 的 BigDecimal。注意,這不是模操作(結果可以為負)​</code>​​<code>​System.out.println(bd_div + " " + bd_dti + " " + bd_tem + " " + bd_rem + " " + bd_tem.equals(bd_rem));//2.5 2 1 1 true​</code>​

​<code>​BigDecimal[] array = bd1.divideAndRemainder(bd2);​</code>​​<code>​System.out.println(Arrays.toString(array) + " " + array[0].equals(bd_dti) + " " + array[1].equals(bd_rem));//[2, 1] true true​</code>​

BigDecimal  abs()  傳回 BigDecimal,其值為此 BigDecimal 的絕對值,其标度為 this.scale()。

BigDecimal  negate()  傳回 BigDecimal,其值為 (-this),其标度為 this.scale()。

BigDecimal  plus()  傳回 BigDecimal,其值為 (+this),其标度為 this.scale()。此方法僅傳回此 BigDecimal,該方法與一進制減方法 negate() 對稱

BigDecimal  abs(MathContext mc)  傳回其值為此 BigDecimal 絕對值的 BigDecimal(根據上下文設定進行舍入)。

BigDecimal  negate(MathContext mc)  傳回其值為 (-this) 的 BigDecimal(根據上下文設定進行舍入)。

BigDecimal  plus(MathContext mc)  傳回其值為 (+this) 的 BigDecimal(根據上下文設定進行舍入)。此方法的效果與 round(MathContext) 方法的效果相同。

【最大最小值】

BigDecimal  max(BigDecimal val)  傳回此 BigDecimal 和 val 的最大值。根據 compareTo 方法的定義,如果它們相等,則傳回 this。

BigDecimal  min(BigDecimal val)  傳回此 BigDecimal 和 val 的最小值。根據 compareTo 方法的定義,如果它們相等,則傳回 this。

【移動小數點】

BigDecimal  movePointLeft(int n)  傳回一個 BigDecimal,它等效于将該值的小數點向左移動 n 位。如果 n 為非負數,則調用僅将 n 添加到該标度。如果 n 為負數,則該調用等效于 movePointRight(-n)。此調用傳回的 BigDecimal 的值為 (this * 10^-n),标度為 max(this.scale()+n, 0)。

BigDecimal  movePointRight(int n)  傳回一個 BigDecimal,它等效于将該值的小數點向右移動 n 位。如果 n 為非負數,則該調用僅從該标度減去 n。如果 n 為負,則該調用等效于 movePointLeft(-n)。此調用傳回的 BigDecimal 的值為 (this * 10^n),标度為 max(this.scale()-n, 0)。

【其他方法】

BigDecimal  stripTrailingZeros()  傳回數值上等于此小數,但從該表示形式移除所有尾部零的 BigDecimal。

BigDecimal  ulp()  傳回此 BigDecimal 的 ulp(最後一位的機關)的大小。

BigDecimal  round(MathContext mc)  傳回根據 MathContext 設定進行舍入後的 BigDecimal。如果精度設定為 0,則不進行任何舍入操作。此方法的效果與 plus(MathContext) 方法的效果相同。

【基本收縮轉換】

int  intValue()  将此 BigDecimal 轉換為 int。此轉換類似于 Java Language Specification 中定義的從 double 到 short 的 基本收縮轉換:将丢棄此 BigDecimal 的所有小數部分,并且如果生成的 " BigInteger" 太大而不适合用 int 表示,則僅傳回 32 位低位位元組。注意,此轉換會丢失關于此 BigDecimal 值的總大小和精度的資訊,并傳回帶有相反符号的結果。

long  longValue()  将此 BigDecimal 轉換為 long。此轉換類似于 Java Language Specification 中定義的從 double 到 short 的 基本收縮轉換:将丢棄此 BigDecimal 的小數部分,并且如果生成的 " BigInteger" 太大而不适合用 long 表示,則僅傳回 64 位低位位元組。注意,此轉換會丢失關于此 BigDecimal 值的總大小和精度的資訊,并傳回帶有相反符号的結果。

float  floatValue()  将此 BigDecimal 轉換為 float。此轉換類似于 Java Language Specification 中定義的從 double 到 float 的 基本收縮轉換:如此 BigDecimal 的值太大而不能表示為 float,則将其适當地轉換為 Float.NEGATIVE_INFINITY 或 Float.POSITIVE_INFINITY。注意,即使在傳回值為有限值的情況下,此轉換也可能丢失關于 BigDecimal 值精度的資訊。

double  doubleValue()  将此 BigDecimal 轉換為 double。此轉換類似于 Java Language Specification 中定義的從 double 到 float 的 基本收縮轉換:如果此 BigDecimal 的數量太大而不能表示為 double,則将其适當地轉換為 Double.NEGATIVE_INFINITY 或 Double.POSITIVE_INFINITY。注意,即使在傳回值為有限值的情況下,此轉換也可能丢失關于 BigDecimal 值精度的資訊。

【轉換為基本資料類型】

byte  byteValueExact()  将此 BigDecimal 轉換為 byte,以檢查丢失的資訊。如果此 BigDecimal 具有非零小數部分,或者超出 byte 結果的可能範圍,則抛出 ArithmeticException。

short  shortValueExact()  将此 BigDecimal 轉換為 short,以檢查丢失的資訊。如果此 BigDecimal 具有非零小數部分,或者超出 short 結果的可能範圍,則抛出 ArithmeticException。

int  intValueExact()  将此 BigDecimal 轉換為 int,以檢查丢失的資訊。如果此 BigDecimal 具有非零小數部分,或者超出 int 結果的可能範圍,則抛出 ArithmeticException。

long  longValueExact()  将此 BigDecimal 轉換為 long,以檢查丢失的資訊。如果此 BigDecimal 具有非零小數部分,或者超出 long 結果的可能範圍,則抛出 ArithmeticException。

String  toString()  傳回此 BigDecimal 的字元串表示形式,如果需要指數,則使用【科學記數法】。

String  toEngineeringString()  傳回此 BigDecimal 的字元串表示形式,需要指數時,則使用【工程計數法】。

傳回如 toString() 方法中所描述的表示 BigDecimal 的字元串,不包括使用指數記數法的情況,将十的幂調整為三的倍數(工程記數法),這樣,非零值的整數部分的範圍是 1 到 999。如果對零值使用指數記數法,則使用小數點和小數的一(或二)個零數字,以便保留零值的标度。

String  toPlainString()  傳回【不帶指數字段】的此 BigDecimal 的字元串表示形式。

BigDecimal 小數 浮點數 精度 财務計算

BigInteger  toBigInteger()  将此 BigDecimal 轉換為 BigInteger。

BigInteger  toBigIntegerExact()  将此 BigDecimal 轉換為 BigInteger,以檢查丢失的資訊。

BigInteger  unscaledValue()  傳回其值為此 BigDecimal 的非标度值 的 BigInteger。計算 (this * 10^this.scale())。

int  compareTo(BigDecimal val)  将此 BigDecimal 與指定的 BigDecimal 比較。

int  hashCode()  傳回此 BigDecimal 的哈希碼。

boolean  equals(Object x)  比較此 BigDecimal 與指定的 Object 的相等性。

2017-8-26

&lt;wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;"&gt;

&lt;/wiz_tmp_tag&gt;