/* BigDecimal类
*
* 现象:java中double类型计算时可能出现精度丢失问题。比如在对一系列double数值进行累加的时候:3.41+5.2+56.2+23.3+... (这类两位小数的价钱),结果会出现103.00000000000001这种结果
* 原因:用2进制表示10进制小数时,部分小数只是近似的表示。
* 解决方法:使用BigDecimal类进行货币的运算。
* 1.定义变量:
* double d1=3.1415926;
* String s1="9.87654321";
* BigDecimal bd1=new BigDecimal(d1);//BigDecimal(double)//注意最好的初始化方法是把double值转变为String,否则仍可能出现精度丢失问题。
* BigDecimal bd2=new BigDecimal(d2);//BigDecimal(String)
* 2.加减乘除模:
* bd1.add(bd2);//加法add
* bd1.add(bd2.negate());//求反negate()
* bd1.multiply(bd2);//multiply乘法
* bd1.divide(bd2);//divide除法
* bd1.remainder(bd2);//remainder求模
* 3.输出数值:
* double d2=bd1.doubleValue();
* int i1=bd1.intValue();
* 4.舍入
* a.RoundingMode枚举
* 使用方法:RoundingMode.HALF_UP
CEILING
向正无限大方向舍入的舍入模式。->oo
UP
远离零方向舍入的舍入模式。0->
DOWN
向零方向舍入的舍入模式。->0
FLOOR
向负无限大方向舍入的舍入模式。->-oo
HALF_UP
四舍五入:向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向上舍入。
HALF_DOWN
向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向下舍入。
HALF_EVEN
向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
UNNECESSARY
用于断言请求的操作具有精确结果的舍入模式,因此不需要舍入。
* b.MathContext 描述数字运算符的某些规则
MathContext(int setPrecision)
构造一个新的 MathContext,它具有指定的精度和 HALF_UP 舍入模式。
MathContext(int setPrecision, RoundingMode setRoundingMode)
构造一个新的 MathContext,它具有指定的精度和舍入模式。
MathContext(String val)
根据字符串构造一个新的 MathContext。
* 注意Precision包括整数部分,Scale只包括小数部分。
* 5.精度问题
* bd1.divide(bd2,3,RoundingMode.HALF_UP)//divide(BigDecimal divisor, int scale, int roundingMode)
* 结果保留3位小数
* bd1.multiply(bd2,new MathContext(5,RoundingMode.HALF_UP))//multiply(BigDecimal multiplicand, MathContext mc)
* 结果精度为5
* 6.字段:
* BigDecimal.ONE
* BigDecimal.TEN
* BigDecimal.ZERO
* 折半向上取整
* bd1.divide(BigDecimal.ONE.add(BigDecimal.ONE),0,RoundingMode.CEILING)
*/
import java.math.*;
public class GameInfo {
private String gameName;
private BigDecimal cardNum;
private BigDecimal setPrice;
private BigDecimal avrValueInUSD;
private BigDecimal avrValueInCNY;
private BigDecimal exRate=new BigDecimal(6.25);
public double getAvrValueInCNY() {
return avrValueInCNY.doubleValue();
}
public double getAvrValueInUSD() {
return avrValueInUSD.doubleValue();
}
public String getName() {
return gameName;
}
public GameInfo(String gameName, int cardNum, String setPrice) {
super();
this.gameName = gameName;
this.cardNum = new BigDecimal(cardNum);
this.setPrice =new BigDecimal(setPrice);
}
private void calVal() {
BigDecimal canObtain=cardNum.divide(BigDecimal.ONE.add(BigDecimal.ONE), 0, RoundingMode.CEILING);//double obtain = Math.ceil(cardNum / 2);
avrValueInUSD = setPrice.divide(cardNum,3,RoundingMode.HALF_UP).multiply(canObtain).add(canObtain.divide(BigDecimal.TEN.multiply(BigDecimal.TEN)).multiply(BigDecimal.ONE.add(BigDecimal.ONE)).negate());// - obtain * 0.02;
avrValueInCNY = avrValueInUSD.multiply(exRate,new MathContext(5,RoundingMode.HALF_UP));
}
@Override//
public String toString() {
if(null==avrValueInUSD){
calVal();
}
return "GameInfo [Game: " + gameName + ", Card number per set: " + cardNum
+ ", Price per badge: " + setPrice + ",average profit: "
+ avrValueInUSD + " USD = "+ avrValueInCNY + " CNY]";
}
}
BigDecimal类——解决double精度丢失
最新推荐文章于 2024-01-17 11:58:06 发布