Java中BigDecimal类型数据保留小数的精度设置

最近工作中碰到了很多关于BigDecimal类型数据的操作,而关于保留几位小数和保留的方法以前没怎么使用过。查阅资料并且亲自试验得到了关于BigDecimal的几种保留小数的方法。

首先定义几个常量供后续使用

import java.math.BigDecimal;


public class Constants {
    public static final BigDecimal bigDecimal1 = new BigDecimal("2.34");
    public static final BigDecimal bigDecimal2 = new BigDecimal("2.35");
    public static final BigDecimal bigDecimal3 = new BigDecimal("2.36");
    public static final BigDecimal bigDecimal4 = new BigDecimal("2.45");
    public static final BigDecimal bigDecimal5 = new BigDecimal("2.55");
    public static final BigDecimal bigDecimal6 = new BigDecimal("2.30");
    public static final BigDecimal bigDecimal7 = new BigDecimal("-2.34");
    public static final BigDecimal bigDecimal8 = new BigDecimal("-2.35");
    public static final BigDecimal bigDecimal9 = new BigDecimal("-2.36");
    public static final BigDecimal bigDecimal10 = new BigDecimal("-2.45");
    public static final BigDecimal bigDecimal11= new BigDecimal("-2.55");
    public static final BigDecimal bigDecimal12 = new BigDecimal("-2.30");
    public static final BigDecimal bigDecimal13 = new BigDecimal("2.355");
}

注意:BigDecimal的定义必须使用字符串形式传参,不能直接数字传参,不然精度依然会有损失,这些保留小数的方法可能不会生效,并产生一些不知道如何解释的现象。

BigDecimal可以使用public BigDecimal setScale(int newScale, int roundingMode)方法进行保留小数位数的操作,其中newScale为保留的位数,roundingMode为保留方法一共7种参数:

一:ROUND_DOWN

import java.math.BigDecimal;
/**
 *  ROUND_DOWN --> 直接删除多余的小数位
 *  这种方式得到的绝对值不会比原数大
 */
public class ROUND_DOWN {
    public static void main(String[] args) {
        System.out.println(Constants.bigDecimal1.setScale(1, BigDecimal.ROUND_DOWN));
        System.out.println(Constants.bigDecimal2.setScale(1, BigDecimal.ROUND_DOWN));
        System.out.println(Constants.bigDecimal3.setScale(1, BigDecimal.ROUND_DOWN));
        System.out.println(Constants.bigDecimal6.setScale(1, BigDecimal.ROUND_DOWN));
        System.out.println(Constants.bigDecimal7.setScale(1, BigDecimal.ROUND_DOWN));
        System.out.println(Constants.bigDecimal8.setScale(1, BigDecimal.ROUND_DOWN));
        System.out.println(Constants.bigDecimal9.setScale(1, BigDecimal.ROUND_DOWN));
        System.out.println(Constants.bigDecimal12.setScale(1, BigDecimal.ROUND_DOWN));
    }
}

 运行结果:

可以看出这种方法会直接截掉多余的部分。

二、ROUND_UP

import java.math.BigDecimal;
/**
 *  ROUND_UP --> 在最后一位直接加1
 *  这种方式得到绝对值的不会比原数小
 *  注意,如果原数精度与需求精度一致,不会改变
 */
public class ROUND_UP {
    public static void main(String[] args) {
        System.out.println(Constants.bigDecimal1.setScale(1, BigDecimal.ROUND_UP));
        System.out.println(Constants.bigDecimal2.setScale(1, BigDecimal.ROUND_UP));
        System.out.println(Constants.bigDecimal3.setScale(1, BigDecimal.ROUND_UP));
        System.out.println(Constants.bigDecimal6.setScale(1, BigDecimal.ROUND_UP));
        System.out.println(Constants.bigDecimal7.setScale(1, BigDecimal.ROUND_UP));
        System.out.println(Constants.bigDecimal8.setScale(1, BigDecimal.ROUND_UP));
        System.out.println(Constants.bigDecimal9.setScale(1, BigDecimal.ROUND_UP));
        System.out.println(Constants.bigDecimal12.setScale(1, BigDecimal.ROUND_UP));
    }
    
}

运行结果:

可以看出这种方式是在最后一位直接+1,需要注意的是如果需求精度和原精度一致,不会发生变化。

三、ROUND_CEILING

import java.math.BigDecimal;
/**
 *  ROUND_CEILING --> 正数时与ROUND_UP一致,负数时与ROUND_DOWN一致 
 */
public class ROUND_CEILING {
    public static void main(String[] args) {
        System.out.println(Constants.bigDecimal1.setScale(1, BigDecimal.ROUND_CEILING));
        System.out.println(Constants.bigDecimal2.setScale(1, BigDecimal.ROUND_CEILING));
        System.out.println(Constants.bigDecimal3.setScale(1, BigDecimal.ROUND_CEILING));
        System.out.println(Constants.bigDecimal6.setScale(1, BigDecimal.ROUND_CEILING));
        System.out.println(Constants.bigDecimal7.setScale(1, BigDecimal.ROUND_CEILING));
        System.out.println(Constants.bigDecimal8.setScale(1, BigDecimal.ROUND_CEILING));
        System.out.println(Constants.bigDecimal9.setScale(1, BigDecimal.ROUND_CEILING));
        System.out.println(Constants.bigDecimal12.setScale(1, BigDecimal.ROUND_CEILING));
    }
}

运行结果:

和前两个结果相比可以看出,这种保留方式如果是正数和ROUND_UP一致,如果是负数,和ROUND_DOWN一致。

四、ROUNU_FLOOR

import java.math.BigDecimal;
/**
 *  ROUND_FLOOR --> 正数时与Round_DOWN一致,负数时与ROUND_UP一致
 */
public class ROUNU_FLOOR {
    public static void main(String[] args) {
        System.out.println(Constants.bigDecimal1.setScale(1,BigDecimal.ROUND_FLOOR));
        System.out.println(Constants.bigDecimal2.setScale(1,BigDecimal.ROUND_FLOOR));
        System.out.println(Constants.bigDecimal3.setScale(1,BigDecimal.ROUND_FLOOR));
        System.out.println(Constants.bigDecimal6.setScale(1,BigDecimal.ROUND_FLOOR));
        System.out.println(Constants.bigDecimal7.setScale(1,BigDecimal.ROUND_FLOOR));
        System.out.println(Constants.bigDecimal8.setScale(1,BigDecimal.ROUND_FLOOR));
        System.out.println(Constants.bigDecimal9.setScale(1,BigDecimal.ROUND_FLOOR));
        System.out.println(Constants.bigDecimal12.setScale(1,BigDecimal.ROUND_FLOOR));
    }
}

运行结果:

和一与二的结果相比,发现如果是正数,和ROUND_DOWN方法一致,如果是负数,和ROUND_UP方法一致。

五、ROUND_HALF_UP

import java.math.BigDecimal;
/**
 *  ROUND_HALF_UP --> 四舍五入
 */
public class ROUND_HALF_UP {
    public static void main(String[] args) {
        System.out.println(Constants.bigDecimal1.setScale(1, BigDecimal.ROUND_HALF_UP));
        System.out.println(Constants.bigDecimal2.setScale(1, BigDecimal.ROUND_HALF_UP));
        System.out.println(Constants.bigDecimal3.setScale(1, BigDecimal.ROUND_HALF_UP));
        System.out.println(Constants.bigDecimal7.setScale(1, BigDecimal.ROUND_HALF_UP));
        System.out.println(Constants.bigDecimal8.setScale(1, BigDecimal.ROUND_HALF_UP));
        System.out.println(Constants.bigDecimal9.setScale(1, BigDecimal.ROUND_HALF_UP));
    }
}

运行结果:

这是一种我们最熟悉的保留小数的方法:四舍五入。

六:ROUND_HALF_DOWN

import java.math.BigDecimal;
/**
 *  ROUND_HALF_DOWN --> 五舍六入
 */
public class ROUND_HALF_DOWN {
    public static void main(String[] args) {
        System.out.println(Constants.bigDecimal1.setScale(1, BigDecimal.ROUND_HALF_DOWN));
        System.out.println(Constants.bigDecimal2.setScale(1, BigDecimal.ROUND_HALF_DOWN));
        System.out.println(Constants.bigDecimal3.setScale(1, BigDecimal.ROUND_HALF_DOWN));
        System.out.println(Constants.bigDecimal7.setScale(1, BigDecimal.ROUND_HALF_DOWN));
        System.out.println(Constants.bigDecimal8.setScale(1, BigDecimal.ROUND_HALF_DOWN));
        System.out.println(Constants.bigDecimal9.setScale(1, BigDecimal.ROUND_HALF_DOWN));
        System.out.println(Constants.bigDecimal13.setScale(1, BigDecimal.ROUND_HALF_DOWN));
    }
}

运行结果:

这种保留方法是五舍六入,当然有一点要注意,这里的5不是看保留的后一位是不是5而是舍弃掉的是否大于5,比如2.355,舍掉的部分是0.055,大于0.5,这里就是进位,而不是舍弃了。
七、ROUND_HALF_EVEN

import java.math.BigDecimal;
/**
 * ROUND_HALE_EVEN --> 四舍六入五看奇進偶不進
 */
public class ROUND_HALF_EVEN {
    public static void main(String[] args) {
        System.out.println(Constants.bigDecimal1.setScale(1, BigDecimal.ROUND_HALF_EVEN));
        System.out.println(Constants.bigDecimal2.setScale(1, BigDecimal.ROUND_HALF_EVEN));
        System.out.println(Constants.bigDecimal3.setScale(1, BigDecimal.ROUND_HALF_EVEN));
        System.out.println(Constants.bigDecimal4.setScale(1, BigDecimal.ROUND_HALF_EVEN));
        System.out.println(Constants.bigDecimal5.setScale(1, BigDecimal.ROUND_HALF_EVEN));
        System.out.println(Constants.bigDecimal7.setScale(1, BigDecimal.ROUND_HALF_EVEN));
        System.out.println(Constants.bigDecimal8.setScale(1, BigDecimal.ROUND_HALF_EVEN));
        System.out.println(Constants.bigDecimal9.setScale(1, BigDecimal.ROUND_HALF_EVEN));
        System.out.println(Constants.bigDecimal10.setScale(1, BigDecimal.ROUND_HALF_EVEN));
        System.out.println(Constants.bigDecimal11.setScale(1, BigDecimal.ROUND_HALF_EVEN));
    }
}

运行结果:

这种保留方法被称为四舍六入五成双。如果被舍掉的数字是5,看5前面的一位。如果是奇数就进位,如果是偶数就直接舍掉。这种保留方法在进行大面积计算的时候,使得最后的误差可以趋近于0。在统计学的角度四舍六入比四舍五入更加科学。

八、ROUND_UNNECESSARY

这个参数表示计算结果就是精确的,不需要舍入操作

import java.math.BigDecimal;


public class ROUND_UNNECESSARY {
    public static void main(String[] args) {
        //System.out.println(Constants.bigDecimal1.setScale(0, BigDecimal.ROUND_UNNECESSARY));
        //System.out.println(Constants.bigDecimal1.setScale(1, BigDecimal.ROUND_UNNECESSARY));
        //System.out.println(Constants.bigDecimal1.setScale(2, BigDecimal.ROUND_UNNECESSARY));
        System.out.println(Constants.bigDecimal1.setScale(3, BigDecimal.ROUND_UNNECESSARY));
    }
}

将前两个注释放开后的运行结果为:

对有精确结果的数据进行舍入操作就会抛出ArithmeticException异常

而保留2位则会输出本来的结果,保留3位则会在后面补0,运行结果如图

一般进行大量计算的时候会使用四舍六入即ROUND_HALF_EVEN这种模式,别的情况根据具体需求进行不同的选择。

 

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值