但行好事
莫论前程❤

BigDecimal使用教程

金融放心算钱时,常用反减操作,来避免钱因为除不尽而丢失。
反减:最后一个月的钱等于总金额-前几个月的总额

构造器

BigDecimal(int)       创建一个具有参数所指定整数值的对象。
BigDecimal(double)    创建一个具有参数所指定双精度值的对象。
BigDecimal(long)      创建一个具有参数所指定长整数值的对象。
BigDecimal(String)    创建一个具有参数所指定以字符串表示的数值的对象。

这几个都是常用的构造器,他们返回的对象都是BigDecimal对象。换而言之, 将各个类型的值转换为BigDecimal对象,就是通过构造器。
反过来说,将BigDecimal对象转换为其他类型的对象,我们通过以下几种:

toString()                将BigDecimal对象的数值转换成字符串。
doubleValue()          将BigDecimal对象中的值以双精度数返回。
floatValue()             将BigDecimal对象中的值以单精度数返回。
longValue()             将BigDecimal对象中的值以长整数返回。
intValue()               将BigDecimal对象中的值以整数返回。

比较大小和加减乘除

比较大小:

int a = bigdemical.compareTo(bigdemical2)
//a = -1,表示bigdemical小于bigdemical2;
//a = 0,表示bigdemical等于bigdemical2;
//a = 1,表示bigdemical大于bigdemical2;

Boolean flag = value1.compareTo(BigDecimal.ZERO) == 1 && value1.compareTo(BigDecimal.ONE) == -1;
if (flag) {
    System.out.println("value1大于0小于1");
}

常用方法:

BigDecimal b1 = new BigDecimal("20");
BigDecimal b2 = new BigDecimal("30");


b1.add(b2) :加法,求两个BigDecimal类型数据的和。
b1.subtract(b2):减法,求两个BigDecimal类型数据的差。
b1.multiply(b2):乘法,求两个BigDecimal类型数据的积。
b1.remainder(b2):求余数,求b1除以b2的余数。
b1.max(b2) : 最大数,求两个BigDecimal类型数据的最大值
b1.min(b2) : 最小数,求两个BigDecimal类型数据的最小值。
bi.abs():绝对值,求BigDecimal类型数据的绝对值。
b1.negate():相反数,求BigDecimal类型数据的相反数。

这里把除法单独拉出来

BigDecimal divide(BigDecimal divisor, int scale, int roundingMode)

除法 divide有三个参数的方法,第一参数表示除数,第二个参数表示小数点后保留位数,第三个参数表示取舍规则。只有在作除法运算或四舍五入时才用到取舍规则。 因为BigDecimal除法可能出现不能整除的情况,比如 4.5/1.3,这时会报错java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result。所以当我们用三参数的除法方法时,规定了保留几位小数以及你的保留方式,就可以避免异常。

取舍规则

ROUND_UP //向远离0的方向舍入,即进位处理,2.35变成2.4 
ROUND_DOWN //向零方向舍入,即直接删除多余的小数位,如2.35会变成2.3 
ROUND_CEILING //向正无穷方向舍入
ROUND_FLOOR //向负无穷方向舍入
ROUND_HALF_DOWN  //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.5
ROUND_HALF_EVEN  //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP,如果是偶数,使用ROUND_HALF_DOWN
ROUND_HALF_UP  //向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6
ROUND_UNNECESSARY //计算结果是精确的,不需要舍入模式

我们最常用的四舍五入应该是 ROUND_HALF_UP

Note that this is the rounding mode that most of us were taught in grade school.

源码中的注释也解释了这一点。
这里说下除法里的第三个参数,

 a.divide(b,2,RoundingMode.HALF_UP)

这里RoundingMode其实是个枚举类,点进去源码可以看到其实他就是匹配到几种取舍规则

UP(BigDecimal.ROUND_UP),       //      进位处理,2.35变成2.4 
DOWN(BigDecimal.ROUND_DOWN),   //      直接删除多余的小数位,如2.35会变成2.3 
CEILING(BigDecimal.ROUND_CEILING),
FLOOR(BigDecimal.ROUND_FLOOR),
HALF_UP(BigDecimal.ROUND_HALF_UP),     //     四舍五入,2.35变成2.4
HALF_DOWN(BigDecimal.ROUND_HALF_DOWN), //   四舍五入,2.35变成2.3,如果是5则向下舍
HALF_EVEN(BigDecimal.ROUND_HALF_EVEN),
UNNECESSARY(BigDecimal.ROUND_UNNECESSARY);

而最常用的就是 HALF_UP 也就是四舍五入。

那如果我们在乘法或者加法减法中也要保留几位或者四舍五入,该怎么操作呢?

设置精度–四舍五入

  • BigDecimal中有一个setScale()方法,用于格式化小数点
    第一个参数就是你要保留几位,第二个可填的参数就是取舍规则。
setScale(1)                        
setScale(1,BigDecimal.ROUND_DOWN)   
setScale(1,BigDecimal.ROUND_UP)     
setScale(1,BigDecimal.ROUND_HALF_UP)  
setScaler(1,BigDecimal.ROUND_HALF_DOWN) 

如果你第二个参数不加,仅仅想保留几位,他在源码中会自动帮你选择默认的规则【精确结果】。

public BigDecimal setScale(int newScale) {
        return setScale(newScale, ROUND_UNNECESSARY);
    }
/**
     * Rounding mode to assert that the requested operation has an exact
     * result, hence no rounding is necessary.  If this rounding mode is
     * specified on an operation that yields an inexact result, an
     * {@code ArithmeticException} is thrown.
     */
    public final static int ROUND_UNNECESSARY =  7;

源码中提及,当我们需要精确结果的时候,可以用这种取舍方式,但是如果你的结果不精确就会抛出异常。

栗子:

BigDecimal b1 = new BigDecimal("3.5");    
BigDecimal b2 = new BigDecimal("7.7");
b1.divide(b2).setScale(2);

Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
    at java.math.BigDecimal.divide(BigDecimal.java:1690)

第二种设置精度的方式

DecimalFormat df = new DecimalFormat("#.00");
df.format(bigDecimalTwo);
赞(1) 打赏
未经允许不得转载:刘鹏博客 » BigDecimal使用教程
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!

 

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏