bigdecimal不保留小数_金钱要使用BigDecimal数据类型(使用double的已经被公司开除了)...
一:簡(jiǎn)介
Java中的簡(jiǎn)單浮點(diǎn)數(shù)類型float和double不能夠進(jìn)行運(yùn)算,或者運(yùn)算會(huì)丟失精度,不光是Java,在其它很多編程語(yǔ)言中也有這樣的問(wèn)題。在大多數(shù)情況下,計(jì)算的結(jié)果是準(zhǔn)確的,float和double只能用來(lái)做科學(xué)計(jì)算或者是工程計(jì)算,在商業(yè)計(jì)算中我們要用 java.math.BigDecimal
// 浮點(diǎn)型計(jì)算不準(zhǔn)確示例@Test
public void testDouble(){
// 0.060000000000000005
System.out.println(0.05+0.01);
// 0.5800000000000001
System.out.println(1.0-0.42);
// 401.49999999999994
System.out.println(4.015*100);
// 1.2329999999999999
System.out.println(123.3/100);
// 4.01 四舍五入保留兩位
System.out.println(Math.round(4.015*100)/100.0);
}
二:BigDecimal
BigDecimal有多種構(gòu)造函數(shù),常用的有2種,其中有一種不建議使用,就是double構(gòu)造方式,建議使用String構(gòu)造方式。
// 強(qiáng)制使用String的構(gòu)造函數(shù),double也有可能計(jì)算不太準(zhǔn)確// 原則是使用BigDecimal并且一定要用String來(lái)夠造。
public BigDecimal(String val);
public BigDecimal(double val);BigDecimal也定義了幾個(gè)常用的值,0、1、10,靜態(tài)的,可以通過(guò)類名直接引用BigDecimal.ZERO
public static final BigDecimal ZERO = zeroThroughTen[0];
/**
* The value 1, with a scale of 0.
*
* @since 1.5
*/
public static final BigDecimal ONE = zeroThroughTen[1];
/**
* The value 10, with a scale of 0.
*
* @since 1.5
*/
public static final BigDecimal TEN = zeroThroughTen[10];
三:工具類
由于構(gòu)造方法要用String對(duì)應(yīng)的構(gòu)造方法,如果我們要做一個(gè)加法運(yùn)算,需要先將兩個(gè)浮點(diǎn)數(shù)轉(zhuǎn)為String,然后夠造成BigDecimal,在其中一個(gè)上調(diào)用add方法,傳入另一個(gè)作為參數(shù),然后把運(yùn)算的結(jié)果(BigDecimal)再轉(zhuǎn)換為浮點(diǎn)數(shù)。你能夠忍受這么煩瑣的過(guò)程嗎?下面我們提供一個(gè)工具類來(lái)簡(jiǎn)化操作。
import java.math.BigDecimal;/**
* 由于Java的簡(jiǎn)單類型不能夠精確的對(duì)浮點(diǎn)數(shù)進(jìn)行運(yùn)算,這個(gè)工具類提供精
* 確的浮點(diǎn)數(shù)運(yùn)算,包括加減乘除和四舍五入。
*/
public class ArithUtil {
//默認(rèn)除法運(yùn)算精度
private static final int DEF_DIV_SCALE = 10;
/**
* 提供精確的加法運(yùn)算。
* @param v1 被加數(shù)
* @param v2 加數(shù)
* @return 兩個(gè)參數(shù)的和
*/
public static double add(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();
}
/**
* 提供精確的減法運(yùn)算。
* @param v1 被減數(shù)
* @param v2 減數(shù)
* @return 兩個(gè)參數(shù)的差
*/
public static double sub(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}
/**
* 提供精確的乘法運(yùn)算。
* @param v1 被乘數(shù)
* @param v2 乘數(shù)
* @return 兩個(gè)參數(shù)的積
*/
public static double mul(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}
/**
* 提供(相對(duì))精確的除法運(yùn)算,當(dāng)發(fā)生除不盡的情況時(shí),精確到
* 小數(shù)點(diǎn)以后10位,以后的數(shù)字四舍五入。
* @param v1 被除數(shù)
* @param v2 除數(shù)
* @return 兩個(gè)參數(shù)的商
*/
public static double div(double v1,double v2){
return div(v1,v2,DEF_DIV_SCALE);
}
/**
* 提供(相對(duì))精確的除法運(yùn)算。當(dāng)發(fā)生除不盡的情況時(shí),由scale參數(shù)指
* 定精度,以后的數(shù)字四舍五入。
* @param v1 被除數(shù)
* @param v2 除數(shù)
* @param scale 表示表示需要精確到小數(shù)點(diǎn)以后幾位。
* @return 兩個(gè)參數(shù)的商
*/
public static double div(double v1,double v2,int scale){
if(scale<0){
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 提供精確的小數(shù)位四舍五入處理。
* @param v 需要四舍五入的數(shù)字
* @param scale 小數(shù)點(diǎn)后保留幾位
* @return 四舍五入后的結(jié)果
*/
public static double round(double v,int scale){
if(scale<0){
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = new BigDecimal("1");
return b.divide(one,scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
}
四:測(cè)試
@Testpublic void testBigDecimal(){
BigDecimal price = BigDecimal.ZERO;
// 通常建議優(yōu)先使用(String)構(gòu)造函數(shù)
BigDecimal amount = new BigDecimal("6.66");
// 0.06
System.out.println(ArithUtil.add(0.05, 0.01));
// 0.58
System.out.println(ArithUtil.sub(1.0, 0.42));
// 401.5
System.out.println(ArithUtil.mul(4.015, 100));
// 1.233
System.out.println(ArithUtil.div(123.3, 100));
// 4.02
System.out.println(ArithUtil.round(4.015, 2));
// BigDecimal 比較大小使用compareTo方法
// public int compareTo(BigDecimal val);
}
總結(jié)
以上是生活随笔為你收集整理的bigdecimal不保留小数_金钱要使用BigDecimal数据类型(使用double的已经被公司开除了)...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: openssl升级_CVE2020196
- 下一篇: imu与gps之间的时间戳_一个时间戳精