筆記一:DecimalFormat & BigDecimal

一、DecimalFormat(數(shù)字格式化)

例1:
import java.text.DecimalFormat;

public class Test{
    public static void main(String[] args){
        double pi=3.1415927;//圓周率
        //取一位整數(shù) 
        System.out.println(new DecimalFormat("0").format(pi));//3
        //取一位整數(shù)和兩位小數(shù)  
        System.out.println(new DecimalFormat("0.00").format(pi));//3.14
        //取兩位整數(shù)和三位小數(shù),整數(shù)不足部分以0填補(bǔ)。  
        System.out.println(new DecimalFormat("00.000").format(pi));//03.142  
        //取所有整數(shù)部分  
        System.out.println(new DecimalFormat("#").format(pi));//3  
        //以百分比方式計數(shù),并取兩位小數(shù)  
        System.out.println(new DecimalFormat("#.##%").format(pi));//314.16%  
        
        long c=299792458;//光速  
        //顯示為科學(xué)計數(shù)法,并取五位小數(shù)  
        System.out.println(new DecimalFormat("#.#####E0").format(c));//2.99792E8  
        //顯示為兩位整數(shù)的科學(xué)計數(shù)法,并取四位小數(shù)  
        System.out.println(new DecimalFormat("00.####E0").format(c));//29.9792E7  
        //每三位以逗號進(jìn)行分隔。  
        System.out.println(new DecimalFormat(",###").format(c));//299,792,458  
        //將格式嵌入文本  
        System.out.println(new DecimalFormat("光速大小為每秒,###米").format(c)); //光速大小為每秒299,792,458米
    }
}
例2:
DecimalFormat df1 = new DecimalFormat("0.0");   
DecimalFormat df2 = new DecimalFormat("#.#");   
DecimalFormat df3 = new DecimalFormat("000.000");   
DecimalFormat df4 = new DecimalFormat("###.###");   
System.out.println(df1.format(12.34));   //12.3
System.out.println(df2.format(12.34));   //12.3
System.out.println(df3.format(12.34));   //012.340
System.out.println(df4.format(12.34));   //12.34

DecimalFormat percentFormat = new DecimalFormat();   
percentFormat.applyPattern("#0.000%");   
System.out.println(percentFormat.format(0.3052222));//30.522%    

二、BigDecimal(精確計算)

為什么要用到BigDecimal呢?因為在計算小數(shù)的時候經(jīng)常會出現(xiàn)丟失精度的問題,不論是float 還是double都是浮點(diǎn)數(shù),而計算機(jī)是二進(jìn)制的,浮點(diǎn)數(shù)會失去一定的精確度,例如:

System.out.println(1.01 + 2.02);
//輸出結(jié)果是:3.0300000000000002

雙精度浮點(diǎn)型變量double可以處理16位有效數(shù)字。在實際應(yīng)用中,需要對更大或者更小的數(shù)進(jìn)行運(yùn)算的處理。float和double只能用來做科學(xué)計算或者工程計算,在商業(yè)計算中需要用BigDecimal來做精確計算。

BigDecimal創(chuàng)建對象主要有兩種方式:

BigDecimal b1 = new BigDecimal("1.34");//1.34
BigDecimal b2 = BigDecimal.valueOf(1.34);//1.34

錯誤創(chuàng)建的方式

BigDecimal one1 = new BigDecimal(1.34);//1.3400000000000000799360577730112709105014801025390625

除了這兩種外,特殊的像0,1,10可以這樣寫

BigDecimal zero = BigDecimal.ZERO;
BigDecimal one = BigDecimal.ONE;
BigDecimal ten = BigDecimal.TEN;

比較一下BigDecimal.ZERO、new BigDecimal("0")、BigDecimal.valueOf(0)這三者,equals都是true,==的話new BigDecimal("0")就不用看了都new了,而BigDecimal.ZERO == BigDecimal.ZERO為true。

BigDecimal的加減乘除運(yùn)算。

public BigDecimal add(BigDecimal value);//加法
public BigDecimal subtract(BigDecimal value);//減法 
public BigDecimal multiply(BigDecimal value);//乘法
public BigDecimal divide(BigDecimal value);//除法
public static double divide(double v1,double v2,int scale)//除法,精確位數(shù)

除法中的八大取舍模式:

1、ROUND_UP
舍入遠(yuǎn)離零的舍入模式。
在丟棄非零部分之前始終增加數(shù)字(始終對非零舍棄部分前面的數(shù)字加1)。
注意,此舍入模式始終不會減少計算值的大小。
2、ROUND_DOWN
接近零的舍入模式。
在丟棄某部分之前始終不增加數(shù)字(從不對舍棄部分前面的數(shù)字加1,即截短)。
注意,此舍入模式始終不會增加計算值的大小。

3、ROUND_CEILING

接近正無窮大的舍入模式。
如果 BigDecimal 為正,則舍入行為與 ROUND_UP 相同;
如果為負(fù),則舍入行為與 ROUND_DOWN 相同。
注意,此舍入模式始終不會減少計算值。

4、ROUND_FLOOR

接近負(fù)無窮大的舍入模式。
如果 BigDecimal 為正,則舍入行為與 ROUND_DOWN 相同;
如果為負(fù),則舍入行為與 ROUND_UP 相同。
注意,此舍入模式始終不會增加計算值。

5、ROUND_HALF_UP

向“最接近的”數(shù)字舍入,如果與兩個相鄰數(shù)字的距離相等,則為向上舍入的舍入模式。
如果舍棄部分 >= 0.5,則舍入行為與 ROUND_UP 相同;否則舍入行為與 ROUND_DOWN 相同。
注意,這是我們大多數(shù)人在小學(xué)時就學(xué)過的舍入模式(四舍五入)。

6、ROUND_HALF_DOWN

向“最接近的”數(shù)字舍入,如果與兩個相鄰數(shù)字的距離相等,則為上舍入的舍入模式。
如果舍棄部分 > 0.5,則舍入行為與 ROUND_UP 相同;否則舍入行為與 ROUND_DOWN 相同(五舍六入)。

7、ROUND_HALF_EVEN

向“最接近的”數(shù)字舍入,如果與兩個相鄰數(shù)字的距離相等,則向相鄰的偶數(shù)舍入。
如果舍棄部分左邊的數(shù)字為奇數(shù),則舍入行為與 ROUND_HALF_UP 相同;
如果為偶數(shù),則舍入行為與 ROUND_HALF_DOWN 相同。
注意,在重復(fù)進(jìn)行一系列計算時,此舍入模式可以將累加錯誤減到最小。
此舍入模式也稱為“銀行家舍入法”,主要在美國使用。四舍六入,五分兩種情況。
如果前一位為奇數(shù),則入位,否則舍去。
以下例子為保留小數(shù)點(diǎn)1位,那么這種舍入方式下的結(jié)果。
1.15>1.2 1.25>1.2

8、ROUND_UNNECESSARY

斷言請求的操作具有精確的結(jié)果,因此不需要舍入。
如果對獲得精確結(jié)果的操作指定此舍入模式,則拋出ArithmeticException。

不同舍入模式下的舍入操作匯總

image.png

測試補(bǔ)充(e0~e6代表:舍入模式0-7下打印的值)

2.1456:e0: 2.14  e1: 2.13  e2: 2.14  e3: 2.13  e4: 2.14  e5: 2.14  e6: 2.14
2.1346:e0: 2.14  e1: 2.13  e2: 2.14  e3: 2.13  e4: 2.13  e5: 2.13  e6: 2.13
2.1366:e0: 2.14  e1: 2.13  e2: 2.14  e3: 2.13  e4: 2.14  e5: 2.14  e6: 2.14
2.1306:e0: 2.14  e1: 2.13  e2: 2.14  e3: 2.13  e4: 2.13  e5: 2.13  e6: 2.13
2.1300:e0: 2.13  e1: 2.13  e2: 2.13  e3: 2.13  e4: 2.13  e5: 2.13  e6: 2.13

舉個加法的例子,其它類似。

public static double add(double value1 , double value2){
    BigDecimal b1=new BigDecimal(Double.toString(value1));
    BigDecimal b1=new BigDecimal(Double.toString(value1));
    return b1.add(b2).doubleValue();
}

值得注意的是:BigDecimal的運(yùn)算都沒有對原值進(jìn)行操作,而是返回一個新的BigDecimal對象。看例子:

BigDecimal b1 =new BigDecimal("1.34");
System.out.println("b1: " + b1);
BigDecimal b2 =new BigDecimal("2.34");
b1.add(b2);
System.out.println("b1: " + b1);//b1并沒有變

BigDecimal的比較用的是BigDecimal的compareTo方法,將此BigDecimal與指定的BigDecimal比較。根據(jù)此方法,值相等但是有不同標(biāo)度的兩個BigDecimal對象(如,2.0和2.00)被認(rèn)為是相等的。

當(dāng)此BigDecimal在數(shù)字上小于、等于或大于被比較對象時,返回-1、0或1。

BigDecimal one = BigDecimal.valueOf(1);
BigDecimal two = BigDecimal.valueOf(2);
BigDecimal three = one.add(two);
int i1 = one.compareTo(two);//-1
int i2 = two.compareTo(two);//0
int i3 = three.compareTo(two);//1
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容