BigDecimal类——解决double精度丢失

/* 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]";
		}
		
		
	
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值