在實際開發中,難免會遇到資料值的計算,關于小數的兩種浮點型(float,double),也就是單精度與雙精度,
那么就需要一個類幫我們解決一些問題,下面介紹兩種浮點型的區別和BigDecimal類的使用
兩種型別的區別:
1.在記憶體中占有的位元組數:單精度是4位元組,而雙精度是8位元組
2. 有效數字位數:單精度有效位是8位,雙精度是16位
3. 數值取值范圍:單精度表示范圍 -3.40E+38~3.40E+38,雙精度表示范圍 -1.79E+308~-1.79E+308
4. 在程式中處理速度不同:一般來說,CPU處理單精度浮點數的速度比處理雙精度浮點數快(網上是這樣說,還沒有感受過)
5. 兩者在使用定義時:如果定義是不宣告,默認的小數型別就是double,如果要使用float就必須進行強制轉換
6. 例如:float a=1.5; 會編譯報錯,正確的寫法 float a = (float)1.5;或者float a = 1.5f;(f或F都可以不區分大小寫)
BigDecimal類:
先介紹下 BigDecimal 類的常用方法
BigDecimal 類路徑:java.math.BigDecimal,BigDecimal 的父類是一個抽象類Number 類路徑 java.lang.Number
比如很多熟悉的基本型別包裝類:Byte、Long、Integer都來繼承自此類
作用:用于高精度的浮點運算
- 創建 BigDecimal類(構造方法)
new BigDecimal(int) 創建一個具有引數所指定整數值的物件,
new BigDecimal(double) 創建一個具有引數所指定雙精度值的物件,
new BigDecimal(long) 創建一個具有引數所指定長整數值的物件,
new BigDecimal(String) 創建一個具有引數所指定以字串表示的數值的物件,
注:在創建BigDecimal物件時,如果直接傳入的是小數型別的值,有可能會造成精度損失,推薦傳入String型別
- 常用方法
1.BigDecimal add(BigDecimal value); 加法,求兩個BigDecimal型別資料的和,
2.BigDecimal subtract(BigDecimal value); 減法,求兩個BigDecimal型別資料的差,
3.BigDecimal multiply(BigDecimal value); 乘法,求兩個BigDecimal型別資料的積,
4.BigDecimal divide(BigDecimal divisor); 除法,求兩個BigDecimal型別資料的商,
5.BigDecimal remainder(BigDecimal divisor); 求余數,求BigDecimal型別資料除以divisor的余數,
6.BigDecimal max(BigDecimal value); 最大數,求兩個BigDecimal型別資料的最大值,
7.BigDecimal min(BigDecimal value); 最小數,求兩個BigDecimal型別資料的最小值,
8.BigDecimal abs(); 絕對值,求BigDecimal型別資料的絕對值,
9.BigDecimal negate(); 相反數,求BigDecimal型別資料的相反數,
10.BigDecimal setScale(int newScale, int roundingMode); 按指定舍入模式保留小數位數
怎么用?下面給大家舉個加法的例子 BigDecimal add(BigDecimal value);:
@Test
public void decimal() {
/*1.第一個BigDecimal的小數值 1.57361*/
BigDecimal bigDecimal = new BigDecimal("1.57361");
/*2.第二個BigDecimal的小數值 1.5*/
BigDecimal bigDecimal2 = new BigDecimal("1.5");
/*使用第一個BigDecimal下的add(BigDecimal value)方法 去加上bigDecimal2的數值
* 這里就相當于 1.5361 + 1.5*/
BigDecimal add = bigDecimal.add(bigDecimal2);
/*結果:3.07361*/
System.out.println(add);
/*如果還要舍棄后面的多余小數,比如說:只保留兩位小數點
* 引數一:設定需要保留小數的位數
引數二:舍入模式(8種舍入方式下面有詳細介紹)*/
BigDecimal decimal = add.setScale(2, BigDecimal.ROUND_UP);
/*輸出舍入后的值:3.08 (舍入模式會間接影響結果)
比如這里結果其實是3.07,使用的舍入方式向前進了一位*/
System.out.println(decimal);
}
- 獲取 BigDecimal 物件中不同回傳值型別
String toString() 將BigDecimal物件的數值轉換成字串,
double doubleValue() 將BigDecimal物件中的值以雙精度數回傳,
float floatValue() 將BigDecimal物件中的值以單精度數回傳,
long longValue() 將BigDecimal物件中的值以長整數回傳,
int intValue() 將BigDecimal物件中的值以整數回傳,
BigDecimal類的8中不同的舍入方式:
假設現在有一個浮點型小數:1.375411 看看使用下面不同的舍入方式會有什么樣的結果?
1.BigDecimal.ROUND_UP 常量值 = 0 (作用:在保留小數后直接去掉多余的位數)
案例:1.376411 ? 1.376
2.BigDecimal.ROUND_DOWN 常量值 = 1 (作用:在保留小數后向前進一位)
案例:1.376411 ? 1.377
3.BigDecimal.ROUND_CEILING 常量值 = 2 (作用:如果是正數相當于ROUND_DOWN,負數相當于ROUND_UP)
4.BigDecimal.ROUND_FLOOR 常量值 = 3 (作用:如果是正數相當于ROUND_DOWN,ROUND_HALF_UP)
5.BigDecimal.ROUND_HALF_UP 常量值 = 4 (作用:在舍棄部分左邊的數字四舍五入(若舍入部分>=5,就進位))
案例:1.376411 ? 1.376 如果 1.376511 變為 1.377
6.BigDecimal.ROUND_HALF_DOWN 常量值 = 5 (作用:在保留小數后的后一位四舍五入(若舍入部分>5,就進位) 和ROUND_HALF_UP非常相似)
案例:1.376411 ? 1.376,如果是1.376511 ? 1.377
注意 ROUND_HALF_UP與ROUND_HALF_DOWN的作用都相同,區別在前者是舍入部分大于或等于>=5都進位,后者只有舍入部分大于>5才進位
7.BigDecimal.ROUND_HALF_EVEN 常量值 = 6 (作用:如果舍入部分左邊的數字為偶數情況下作用與ROUND_HALF_DOWN相同,為奇數與ROUND_HALF_UP相同)
案例:1.376411 ? 1.376 舍入部分左邊數字為6(偶數),再使用ROUND_HALF_DOWN,舍入部分為411 沒有大于>5 那么不進位(相反之)
再比如:1.375511 ? 1.376 舍入部分左邊數字為5(奇數),再使用ROUND_HALF_UP,舍入部分為511 大于>=5 那么進位(相反之) 1.375 ? 1.376
邏輯: 1.先判斷舍入部分左邊數字為偶數還是奇數
2.再選擇使用ROUND_HALF_DOWN(偶數)還是 ROUND_HALF_UP(奇數)
使用的方式是銀行家舍入:即四舍六入五考慮,五后非零就進一,五后為零看奇偶,五前為偶應舍去,五前為奇要進一(可以去了解下)
8.BigDecimal.ROUND_UNNECESSARY 常量值 = 7 (作用:斷言該小數已經具有精確的結果,因此不需要舍入,否則拋出ArithmeticException例外)
例子:1.376 只要小數位不超過規定的位數(我們這里是3位),超過拋出例外
注:該方法是一個多載方法 java.math.RoundingMode列舉類中就包含上面8個常量
案例:
假設現在有一個浮點型小數我們需要按照我們的要求進行保留小數位:
@Test
public void decimal() {
/*1.創建 BigDecimal類
注:在創建BigDecimal物件時,如果直接傳入的是小數型別的值,有可能會造成精度損失,推薦傳入String型別*/
BigDecimal Decimal = new BigDecimal("1.376411");
/*2.使用BigDecimal.setScale(int newScale, int roundingMode)方法進行小數位的保留
引數一:設定需要保留3位小數
引數二:舍入模式(8種舍入方式上面已經介紹了)
這里就保留3位小數,使用BigDecimal.ROUND_UP方式:在保留小數后直接去掉多余的位數(這里寫對應的常量值也行)*/
Decimal = Decimal.setScale(3, BigDecimal.ROUND_UP);
/*3.獲取回傳型別(可以獲得不同的回傳值型別:long,int,String,double)*/
double value = Decimal.doubleValue();
/*列印輸出*/
System.out.println(value);
/*不同的舍入方式大家可以參照這上面的關于舍入方式詳細介紹都試一試*/
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/224251.html
標籤:java
上一篇:opencv2學習筆記(1)
