一、简介
1、概述
BigDecimal由任意精度的整数非标度值和32位的整数标度(scale)组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以10的负scale次幂。因此,BigDecimal表示的数值是(unscaleValue ×10-scale).
2、构造函数 (主要为了说明double类型的构造函数)
BigDecimal的String和double的构造函数实例:
public static void main(String[] args) { BigDecimal bd1=new BigDecimal(1.22); System.out.println("double value"+bd1); BigDecimal bd2=new BigDecimal("1.22"); System.out.println("String value"+bd2); } 输出结果: double value==>:1.2199999999999999733546474089962430298328399658203125 String value==>:1.22
说明:
1、参数类型为double的构造方法的结果有一定的不可预知性。有人可能认为在Java中写入newBigDecimal(0.1)所创建的BigDecimal正好等于 0.1(非标度值 1,其标度为 1),但是它实际上等于0.1000000000000000055511151231257827021181583404541015625。这是因为0.1无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。这样,传入到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。
2、另一方面,String 构造方法是完全可预知的:写入 newBigDecimal("0.1") 将创建一个 BigDecimal,它正好等于预期的 0.1。因此,比较而言,通常建议优先使用String构造方法。
3、当double必须用作BigDecimal的源时,请注意,此构造方法提供了一个准确转换;它不提供与以下操作相同的结果:先使用Double.toString(double)
方法,然后使用BigDecimal(String)
构造方法,将double转换为String。要获取该结果,请使用static valueOf(double)
方法。
二、BigDecimal的加减乘除(以double类型的参数为示例)
1、加法
/** * 提供精确加法计算的add方法 * @param value1 被加数 * @param value2 加数 * @return 两个参数的和 */ public static double add(double value1,double value2){ BigDecimal b1 = new BigDecimal(Double.valueOf(value1)); BigDecimal b2 = new BigDecimal(Double.valueOf(value2)); return b1.add(b2).doubleValue(); }
2、减法
/** * 提供精确减法运算的sub方法 * @param value1 被减数 * @param value2 减数 * @return 两个参数的差 */ public static double substract(double value1,double value2){ BigDecimal b1 = new BigDecimal(Double.valueOf(value1)); BigDecimal b2 = new BigDecimal(Double.valueOf(value2)); return b1.subtract(b2).doubleValue(); }
3、乘法
/** * 提供精确乘法运算的mul方法 * @param value1 被乘数 * @param value2 乘数 * @return 两个参数的积 */ public static double multiply(double value1,double value2){ BigDecimal b1 = new BigDecimal(Double.valueOf(value1)); BigDecimal b2 = new BigDecimal(Double.valueOf(value2)); return b1.multiply(b2).doubleValue(); }
4、除法
/** * 提供精确的除法运算方法div * @param value1 被除数 * @param value2 除数 * @param scale 精确范围 * @return 两个参数的商 * @throws IllegalAccessException */ public static double divide(double value1,double value2,int scale) throws IllegalAccessException{ //如果精确范围小于0,抛出异常信息 if(scale<0){ throw new IllegalAccessException("精确度不能小于0"); } BigDecimal b1 = new BigDecimal(Double.valueOf(value1)); BigDecimal b2 = new BigDecimal(Double.valueOf(value2)); return b1.divide(b2, scale,BigDecimal.ROUND_HALF_EVEN).doubleValue();
}
注意:对于除法获取精确度的方式有如下:
static int | ROUND_CEILING Rounding mode to round towards positive infinity. 向正无穷方向舍入 |
static int | ROUND_DOWN Rounding mode to round towards zero. 向零方向舍入 |
static int | ROUND_FLOOR Rounding mode to round towards negative infinity. 向负无穷方向舍入 |
static int | ROUND_HALF_DOWN Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round down. 向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5 |
static int | ROUND_HALF_EVEN Rounding mode to round towards the "nearest neighbor" unless both neighbors are equidistant, in which case, round towards the even neighbor. 向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP ,如果是偶数,使用ROUND_HALF_DOWN |
static int | ROUND_HALF_UP Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round up. 向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6 |
static int | ROUND_UNNECESSARY Rounding mode to assert that the requested operation has an exact result, hence no rounding is necessary. 计算结果是精确的,不需要舍入模式 |
static int | ROUND_UP Rounding mode to round away from zero. 向远离0的方向舍入 |
b1.divide(b2, BigDecimal.ROUND_UP).doubleValue();
三、其他