BigDecimal类——解决double精度丢失

来源:互联网 发布:三菱fxplc编程软件 编辑:程序博客网 时间:2024/05/11 05:23
/* 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_UPCEILING           向正无限大方向舍入的舍入模式。->ooUP          远离零方向舍入的舍入模式。0->DOWN           向零方向舍入的舍入模式。->0FLOOR           向负无限大方向舍入的舍入模式。->-ooHALF_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]";}}

0 0