一、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。
不同舍入模式下的舍入操作匯總
測試補(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