BigDecimal學習筆記

qq_36185997發表於2020-11-14

Java語言提供了八種基本型別。六種數字型別(四個整數型,兩個浮點型),一種字元型別,還有一種布林型。

byte:

byte 資料型別是8位、有符號的,以二進位制補碼錶示的整數; 最小值是 -128(-2^7); 最大值是 127(2^7-1); 預設值是
0; byte 型別用在大型陣列中節約空間,主要代替整數,因為 byte 變數佔用的空間只有 int 型別的四分之一; 例子:byte a
= 100,byte b = -50。

short:

short 資料型別是 16 位、有符號的以二進位制補碼錶示的整數 最小值是 -32768(-2^15); 最大值是 32767(2^15 -
1); Short 資料型別也可以像 byte 那樣節省空間。一個short變數是int型變數所佔空間的二分之一; 預設值是 0;
例子:short s = 1000,short r = -20000。 int:

int 資料型別是32位、有符號的以二進位制補碼錶示的整數; 最小值是 -2,147,483,648(-2^31); 最大值是
2,147,483,647(2^31 - 1); 一般地整型變數預設為 int 型別; 預設值是 0 ; 例子:int a =
100000, int b = -200000。

long 資料型別是 64 位、有符號的以二進位制補碼錶示的整數; 最小值是
-9,223,372,036,854,775,808(-2^63); 最大值是 9,223,372,036,854,775,807(2^63 -1); 這種型別主要使用在需要比較大整數的系統上; 預設值是 0L; 例子: long a = 100000L,Long b = -200000L。 "L"理論上不分大小寫,但是若寫成"l"容易與數字"1"混淆,不容易分辯。所以最好大寫。

float:

float 資料型別是單精度、32位、符合IEEE 754標準的浮點數; float 在儲存大型浮點陣列的時候可節省記憶體空間; 預設值是
0.0f; 浮點數不能用來表示精確的值,如貨幣; 例子:float f1 = 234.5f。 double:

double 資料型別是雙精度、64 位、符合IEEE 754標準的浮點數; 浮點數的預設型別為double型別;
double型別同樣不能表示精確的值,如貨幣; 預設值是 0.0d; 例子:double d1 = 123.4。

boolean:
boolean資料型別表示一位的資訊;
只有兩個取值:true 和 false;
這種型別只作為一種標誌來記錄 true/false 情況;
預設值是 false;
例子:boolean one = true。

char:

char型別是一個單一的 16 位 Unicode 字元; 最小值是 \u0000(即為0); 最大值是 \uffff(即為65,535);
char 資料型別可以儲存任何字元; 例子:char letter = ‘A’;。

一、BigDecimal概述

​ Java在java.math包中提供的API類BigDecimal,用來對超過16位有效位的數進行精確的運算。雙精度浮點型變數double可以處理16位有效數,但在實際應用中,可能需要對更大或者更小的數進行運算和處理。一般情況下,對於那些不需要準確計算精度的數字,我們可以直接使用Float和Double處理,但是Double.valueOf(String) 和Float.valueOf(String)會丟失精度。所以開發中,如果我們需要精確計算的結果,則必須使用BigDecimal類來操作。

​ BigDecimal所建立的是物件,故我們不能使用傳統的+、-、*、/等算術運算子直接對其物件進行數學運算,而必須呼叫其相對應的方法。方法中的引數也必須是BigDecimal的物件。構造器是類的特殊方法,專門用來建立物件,特別是帶有引數的物件。

二、BigDecimal常用建構函式

2.1、常用建構函式
BigDecimal(int)

建立一個具有引數所指定整數值的物件

BigDecimal(double)

建立一個具有引數所指定雙精度值的物件

BigDecimal(long)

建立一個具有引數所指定長整數值的物件

BigDecimal(String)

建立一個具有引數所指定以字串表示的數值的物件

三、BigDecimal常用方法詳解

3.1、常用方法
add(BigDecimal)

BigDecimal物件中的值相加,返回BigDecimal物件

subtract(BigDecimal)

BigDecimal物件中的值相減,返回BigDecimal物件

multiply(BigDecimal)

BigDecimal物件中的值相乘,返回BigDecimal物件

divide(BigDecimal)

BigDecimal物件中的值相除,返回BigDecimal物件

toString()

將BigDecimal物件中的值轉換成字串

doubleValue()

將BigDecimal物件中的值轉換成雙精度數

floatValue()

將BigDecimal物件中的值轉換成單精度數

longValue()

將BigDecimal物件中的值轉換成長整數

intValue()

將BigDecimal物件中的值轉換成整數

3.2、BigDecimal大小比較
java中對BigDecimal比較大小一般用的是bigdemical的compareTo方法

int a = bigdemical.compareTo(bigdemical2)
返回結果分析:

a = -1,表示bigdemical小於bigdemical2;
a = 0,表示bigdemical等於bigdemical2;
a = 1,表示bigdemical大於bigdemical2;
舉例:a大於等於b

new bigdemica(a).compareTo(new bigdemical(b)) >= 0

四、BigDecimal格式化

由於NumberFormat類的format()方法可以使用BigDecimal物件作為其引數,可以利用BigDecimal對超出16位有效數字的貨幣值,百分值,以及一般數值進行格式化控制。

以利用BigDecimal對貨幣和百分比格式化為例。首先,建立BigDecimal物件,進行BigDecimal的算術運算後,分別建立對貨幣和百分比格式化的引用,最後利用BigDecimal物件作為format()方法的引數,輸出其格式化的貨幣值和百分比。

NumberFormat currency = NumberFormat.getCurrencyInstance(); //建立貨幣格式化引用 
NumberFormat percent = NumberFormat.getPercentInstance();  //建立百分比格式化引用 
percent.setMaximumFractionDigits(3); //百分比小數點最多3位 

BigDecimal loanAmount = new BigDecimal("15000.48"); //貸款金額
BigDecimal interestRate = new BigDecimal("0.008"); //利率   
BigDecimal interest = loanAmount.multiply(interestRate); //相乘

System.out.println("貸款金額:\t" + currency.format(loanAmount)); 
System.out.println("利率:\t" + percent.format(interestRate)); 
System.out.println("利息:\t" + currency.format(interest)); 

結果:

貸款金額: ¥15,000.48 利率: 0.8% 利息: ¥120.00
BigDecimal格式化保留2為小數,不足則補0:

public class NumberFormat {

public static void main(String[] s){
	System.out.println(formatToNumber(new BigDecimal("3.435")));
	System.out.println(formatToNumber(new BigDecimal(0)));
	System.out.println(formatToNumber(new BigDecimal("0.00")));
	System.out.println(formatToNumber(new BigDecimal("0.001")));
	System.out.println(formatToNumber(new BigDecimal("0.006")));
	System.out.println(formatToNumber(new BigDecimal("0.206")));
}
/**
 * @desc 1.0~1之間的BigDecimal小數,格式化後失去前面的0,則前面直接加上0。
 * 2.傳入的引數等於0,則直接返回字串"0.00"
 * 3.大於1的小數,直接格式化返回字串
 * @param obj傳入的小數
 * @return
 */
public static String formatToNumber(BigDecimal obj) {
	DecimalFormat df = new DecimalFormat("#.00");
	if(obj.compareTo(BigDecimal.ZERO)==0) {
		return "0.00";
	}else if(obj.compareTo(BigDecimal.ZERO)>0&&obj.compareTo(new BigDecimal(1))<0){
		return "0"+df.format(obj).toString();
	}else {
		return df.format(obj).toString();
	}
}

}
結果為:

3.44
0.00
0.00
0.00
0.01
0.21

五、BigDecimal常見異常

5.1、除法的時候出現異常
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result
原因分析:

​ 通過BigDecimal的divide方法進行除法時當不整除,出現無限迴圈小數時,就會拋異常:java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

解決方法:

​ divide方法設定精確的小數點,如:divide(xxxxx,2)

六、BigDecimal總結
6.1、總結
在需要精確的小數計算時再使用BigDecimal,BigDecimal的效能比double和float差,在處理龐大,複雜的運算時尤為明顯。故一般精度的計算沒必要使用BigDecimal。
儘量使用引數型別為String的建構函式。
BigDecimal都是不可變的(immutable)的, 在進行每一次四則運算時,都會產生一個新的物件 ,所以在做加減乘除運算時要記得要儲存操作後的值。
6.2、工具類推薦
package com.vivo.ars.util;
import java.math.BigDecimal;