关于java BigDecimal 的使用,并将其运算方法封装成工具类

最近在做数据统计的时候遇到了double 小数点精度丢失的问题,上网找了一些资料,发现 java 中的 BigDecimal 用于统计的计算更佳,下面把这个问题记录下,时刻提醒自己。

首先,比较一下各个浮点型内容(转自百度回答:https://zhidao.baidu.com/question/2119957025467035427.html):

float 单精度浮点 32bit,


double 双精度浮点64bit,
decimal是高精度 128bit,浮点型。
float double 是 基本类型(primitive type),decimal不是。
float 有效数字7位,范围 ±1.5 × 10E−45 to ±3.4 × 10E38
double 有效数字15/16 位,范围 ±5.0 × 10 E−324 to ±1.7 × 10E308
decimal 有效数字 28/29 位,范围 ±1.0 × 10E−28 to ±7.9 × 10E28
( E -- 下接几次方)

decimal的有效位数很大,达到了28位,但是表示的数据范围却比float和double类型小。
使用的时候会对计算时的性能有影响。
常数写法:
float f = 12.3F; (带F)
double x=12.3; (不带就是double)
decimal d = 12.30M; (带M)

浮点数运算会有精度损失问题,有精度损失时程序不会报告,要程序员自己注意。


了解了上面三种浮点类型,我们就对 decimal 进一步了解了,下面就大致介绍一下java 中的BigDecimal 的使用。

BigDecimal(java.math.BigDecimal)一共有4个够造方法,我在这就主要将他其中的两种:

第一种:BigDecimal(double val)
Translates a double into a BigDecimal.

第二种:BigDecimal(String val)
Translates the String repre sentation of a BigDecimal into a BigDecimal.

我们更建议使用String来构造BigDecimal,这样可以最大程度的避免精度丢失,但前提是String必须是一个数值。


下面提供 BigDecimal 的运算方法,大家可以把这些方法封装成一个工具类,下面贴上代码(代码引用自:https://blog.csdn.net/huiwenjie168/article/details/6998140):

import java.math.BigDecimal;   
/**  
* 由于Java的简单类型不能够精确的对浮点数进行运算,这个工具类提供精  
* 确的浮点数运算,包括加减乘除和四舍五入。  
*/  
public class Arith{ //默认除法运算精度   
private static final int DEF_DIV_SCALE = 10; //这个类不能实例化   
private Arith(){   
}   
/**  
* 提供精确的加法运算。  
* @param v1 被加数  
* @param v2 加数  
* @return 两个参数的和  
*/  
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();   
}   
/**  
* 提供精确的减法运算。  
* @param v1 被减数  
* @param v2 减数  
* @return 两个参数的差  
*/  
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();   
}   
/**  
* 提供精确的乘法运算。  
* @param v1 被乘数  
* @param v2 乘数  
* @return 两个参数的积  
*/  
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();   
}   
/**  
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到  
* 小数点以后10位,以后的数字四舍五入。  
* @param v1 被除数  
* @param v2 除数  
* @return 两个参数的商  
*/  
public static double div(double v1,double v2){   
return div(v1,v2,DEF_DIV_SCALE);   
}   
/**  
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指  
* 定精度,以后的数字四舍五入。  
* @param v1 被除数  
* @param v2 除数  
* @param scale 表示表示需要精确到小数点以后几位。  
* @return 两个参数的商  
*/  
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();   
}   
/**  
* 提供精确的小数位四舍五入处理。  
* @param v 需要四舍五入的数字  
* @param scale 小数点后保留几位  
* @return 四舍五入后的结果  
*/  
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();   
}   
};
至此,关于java BigDecimal 的使用就先讲到这儿,希望此文章能帮助到各位技术开发人员!

你可能感兴趣的:(java基础)