Bigdecimal 數(shù)據(jù)轉(zhuǎn)換精度缺失
使用 new BigDecimal()、.valueof() 和 new BigDecimal("[字符串]")的區(qū)別
構(gòu)造 BigDecimal 對(duì)象常用以下方法:
BigDecimal BigDecimal(double d); //不允許使用
BigDecimal BigDecimal(String s); //常用,推薦使用
static BigDecimal valueOf(double d); //常用,推薦使用
其原因有
- double 參數(shù)的構(gòu)造方法,不允許使用!!!!因?yàn)樗荒芫_的得到相應(yīng)的值;
- String 構(gòu)造方法是完全可預(yù)知的: 寫入 new BigDecimal("0.1") 將創(chuàng)建一個(gè) BigDecimal,它正好等于預(yù)期的0.1; 因此,通常建議優(yōu)先使用 String 構(gòu)造方法;
- 靜態(tài)方法 valueOf(double val) 內(nèi)部實(shí)現(xiàn),仍是將 double 類型轉(zhuǎn)為 String 類型; 這通常是將 double(或float)轉(zhuǎn)化為 BigDecimal 的首選方法;
如下代碼測(cè)試操作:
public class BigDecimalDemo {
public static void main(String[] args) {
Double v1 = 2.43;
Double v2 = 4.0;
System.out.println(new BigDecimal(v1));
System.out.println(new BigDecimal(v2));
System.out.println(new BigDecimal(v1.toString()));
System.out.println(new BigDecimal(v2.toString()));
System.out.println(BigDecimal.valueOf(v1));
System.out.println(BigDecimal.valueOf(v2));
}
}
以上輸出的結(jié)果是:
2.430000000000000159872115546022541821002960205078125
4
2.43
4.0
2.43
4.0
從結(jié)果可以看的出來直接 new BigDecimal()的情況會(huì)出現(xiàn)數(shù)據(jù)精準(zhǔn)度丟失的情況
而. valueof 和 new 字符串的形式卻不會(huì)使精度丟失
我們可以看一下他的源碼:
/**
* Translates a {@code double} into a {@code BigDecimal}, using
* the {@code double}'s canonical string representation provided
* by the {@link Double#toString(double)} method.
*
* <p><b>Note:</b> This is generally the preferred way to convert
* a {@code double} (or {@code float}) into a
* {@code BigDecimal}, as the value returned is equal to that
* resulting from constructing a {@code BigDecimal} from the
* result of using {@link Double#toString(double)}.
*
* @param val {@code double} to convert to a {@code BigDecimal}.
* @return a {@code BigDecimal} whose value is equal to or approximately
* equal to the value of {@code val}.
* @throws NumberFormatException if {@code val} is infinite or NaN.
* @since 1.5
*/
public static BigDecimal valueOf(double val) {
// Reminder: a zero double returns '0.0', so we cannot fastpath
// to use the constant ZERO. This might be important enough to
// justify a factory approach, a cache, or a few private
// constants, later.
return new BigDecimal(Double.toString(val));
}
valueof 的形式是將 double 直接 tostring 為一個(gè)字符串的形式進(jìn)行轉(zhuǎn)換的
BigDecimal 的大小比較
BigDecimal是Java里精確計(jì)算的類枝恋,下面說一下兩個(gè)BigDecimal對(duì)象大小,相等的判斷。
一般的對(duì)象用equals,但是BigDecimal比較特殊讯壶,舉個(gè)例子:
public static void main(String[] args) {
BigDecimal a = new BigDecimal("10.00");
BigDecimal b = new BigDecimal("10");
//equals方式
System.out.println(a.equals(b)); //結(jié)果為: false
//toPlainString再equals
System.out.println(a.toPlainString().equals(b.toPlainString())); //結(jié)果為: false
//longValue方式
System.out.println(a.longValue() == b.longValue()); //結(jié)果為: true
//compareTo
System.out.println(a.compareTo(b) == 0); //結(jié)果為: true
}
看似使用 Long 數(shù)據(jù)類型進(jìn)行比較也可以但是我們看下一個(gè)例子:
public static void main(String[] args) {
BigDecimal a = new BigDecimal("10.300003");
BigDecimal b= new BigDecimal(10.300003);
System.out.println(b.equals(a)); //false
System.out.println(b.toPlainString().equals(a.toPlainString())); //false
System.out.println(b.longValue() == a.longValue()); //true
System.out.println(b.compareTo(a) == 0); //false
}
為什么compareTo方法不可以了,而longValue方式卻還是OK的湾盗。讓我們打印一下伏蚊。
public static void main(String[] args) {
BigDecimal a = new BigDecimal("10.300003");
BigDecimal b= new BigDecimal(10.300003);
System.out.println(b.equals(a)); //false
System.out.println(b.toPlainString().equals(a.toPlainString())); //false
System.out.println(b.longValue() == a.longValue()); //true
System.out.println("b.longValue():"+b.longValue());
System.out.println("a.longValue():"+a.longValue());
System.out.println(b.compareTo(a) == 0); //false
}
而輸出的結(jié)果令我懵逼
false
false
true
b.longValue():10
a.longValue():10
false
我們可以看出longvalue 的結(jié)果是沒有小數(shù)點(diǎn)的所以對(duì) BigDecimal 數(shù)據(jù)類型進(jìn)行比較的時(shí)候還是使用"compareTo"方法
總結(jié): 當(dāng)我們需要使用BigDecimal 進(jìn)行數(shù)據(jù)轉(zhuǎn)換時(shí)一定要注意轉(zhuǎn)換的數(shù)據(jù)類型以及大小比較的唯一方法我們可以對(duì)它的值進(jìn)行<或者>的判斷如:
public static void main(String[] args) {
BigDecimal a = new BigDecimal("10.300003");
BigDecimal b= BigDecimal.valueOf(10.3);
System.out.println(b.compareTo(a) < 0); //true
System.out.println(b.compareTo(a) > 0); //false
}
最后:感謝大家的閱讀