Java 各数据类型计算的精度问题

开发了一个项目,涉及到了价格计算的问题,由于之前考虑的不够周全,所有遇到了好多的类型之间计算出现的精度不准的问题,在这和大家分享一下,说的有不对的直接关闭此网页.

  //直接用int + double 进行运算,可想而知结局是悲惨的
        int g = 2;
		double a = 0.01;
		double b = 0.05;
		double k = g+b+a;
		System.out.println("k:" + k);
        结果:k:2.0599999999999996
        
 ***这个因为如果不同类型的数据进行相加,会将类型统一成一个类型的数据在进行计算,因为double类型的数据占的字节多  所以java编译器会自己帮你把int类型的数据转换成double 类型的数据 然后再实行两个double类型的数据相加*** 

  //当时用float,然后就出现了小数丢失的现像
		float d = 0.01f;
		float e = 0.05f;
		float f = d + e;
		System.out.println("f:" + f);
		
        结果:f:0.060000002
  //接着换下一个double,当时觉得肯定是可以了,但是........
        double a = 0.01;
		double b = 0.05;
		double c = a + b;
		System.out.println("c:" + c);	
		结果:c:0.060000000000000005
		
***并不是所有的小数都可以用二进制浮点数来精确表示的
二进制浮点不可能将0.1——或者10的其它任何次负幂——精确表示为一个长度有限的二进制小数 (看下计算机组成原理中的浮点数的表示方法,好象有不同的标准)***
  

解决的方法可以用BigDecimal类,该类位于java.math包中

基本 加,减,乘,除,保留两位小数,四舍五入等

BigDecimal decimal = new BigDecimal(要计算的参数);
值得注意的是要是想计算的精准一些 ,f要计算的参数最好是字符类型的

类型转换的时候最好用各数据类型包装器,例如:Integer.parseInt(s)等, 像 (int)a 强行转换类型有的时候会有问题

    // 相加
	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();
	}

	// 相减
	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();
	}

	// 相乘
	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();
	}

	
	 /**    
	  *   相除,做除法的时候相对的麻烦一点,涉及的多一些
      *   提供精确的小数位四舍五入处理。    
      *   @param   v1   需要四舍五入的数字
      *   @param   v2   需要四舍五入的数字        
      *   @param   scale   小数点后保留几位    
      *   @return   四舍五入后的结果    
      */     
	public static double round(double v1, double v2, int scale) {
		if (scale < 0) {
			throw new IllegalArgumentException("此参数错误");
		}
		BigDecimal one = new BigDecimal(Double.toString(v1));
		BigDecimal two = new BigDecimal(Double.toString(v2));
		return one.divide(two, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
	} 

以上就是本次开发中遇到的BUG, 菜鸟一个努力学习中 , 多多支持…

关注回复【资料】,免费获取架构资料、视频,还有精心整理的面试题
在这里插入图片描述

发布了29 篇原创文章 · 获赞 135 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/xinzhifu1/article/details/53084133