BigDecimal 八种舍入模式介绍

一、BigDecimal 简介

BigDecimal 类位于 java.math 包中,它提供了更加精确的算术运算,使用户完全控制舍入行为。 如果未指定舍入模式,并且无法表示确切的结果,则抛出异常; 否则,可以通过操作提供适当的 MathContext 对象来进行计算,以选择精度和舍入模式。虽然双精度浮点型变量 double 可以处理16位有效数,但在实际应用中可能需要对更大或者更小的数进行运算和处理。一般情况下,对于那些不需要准确计算精度的数字我们可以直接使用 Float 或 Double 处理,但是 Double.valueOf(String) 和Float.valueOf(String) 会丢失精度。如果我们需要精确计算的结果,则必须使用BigDecimal 类来操作。

【注】使用 BigDecimal 进行计算时,我们不能再使用算术运算符(+、-、*、/)进行算数运算,而是使用 BigDecimal 类提供的 add、subtract、multiply、divide 等方法来进行算数运算。

二、BigDecimal 的舍入模式

BigDecimal 的舍入模式(RoundingMode)包含ROUND_UP、ROUND_DOWN、ROUND_CEILING、ROUND_FLOOR、ROUND_HALF_UP、ROUND_HALF_DOWN、ROUND_HALF_EVEN、ROUND_UNNECESSARY,下面将会对这八种RoundingMode 进行详细说明。

ROUND_UP
/**
 * Rounding mode to round away from zero. Always increments the digit prior to a nonzero discarded fraction.
 * Note that this rounding mode never decreases the magnitude of the calculated value.
 */
public final static int ROUND_UP =  0;

【说明】

该模式,远离零,总是在非零丢弃分数之前增加数字,朝远离数轴的方向进位,正数+1,负数-1。(除保留位数后一位为0以外,其它不管正负号,直接进位)

log.info("BigDecimal.ROUND_UP={}", new BigDecimal("5.5").setScale(0, BigDecimal.ROUND_UP));     // 6
log.info("BigDecimal.ROUND_UP={}", new BigDecimal("1.6").setScale(0, BigDecimal.ROUND_UP));     // 2
log.info("BigDecimal.ROUND_UP={}", new BigDecimal("1.0").setScale(0, BigDecimal.ROUND_UP));     // 1
log.info("BigDecimal.ROUND_UP={}", new BigDecimal("-1.0").setScale(0, BigDecimal.ROUND_UP));    // -1
log.info("BigDecimal.ROUND_UP={}", new BigDecimal("-1.6").setScale(0, BigDecimal.ROUND_UP));    // -2
log.info("BigDecimal.ROUND_UP={}", new BigDecimal("-5.5").setScale(0, BigDecimal.ROUND_UP));    // -6
ROUND_DOWN
/**
 * Rounding mode to round towards zero. Never increments the digit prior to a discarded fraction (i.e., truncates). 
 * Note that this rounding mode never increases the magnitude of the calculated value.
 */
public final static int ROUND_DOWN = 1;

【说明】

该模式向零靠近。永远不要在一个被丢弃的分数前增加数字(即截断)。请注意,这种舍入模式不会增加计算值的大小。采用断言式,截断舍弃对应小数位后面的小数,不考虑任何进位。

log.info("BigDecimal.ROUND_DOWN={}", new BigDecimal("5.5").setScale(0, BigDecimal.ROUND_DOWN));     // 5
log.info("BigDecimal.ROUND_DOWN={}", new BigDecimal("1.6").setScale(0, BigDecimal.ROUND_DOWN));     // 1
log.info("BigDecimal.ROUND_DOWN={}", new BigDecimal("1.0").setScale(0, BigDecimal.ROUND_DOWN));     // 1
log.info("BigDecimal.ROUND_DOWN={}", new BigDecimal("-1.0").setScale(0, BigDecimal.ROUND_DOWN));    // -1
log.info("BigDecimal.ROUND_DOWN={}", new BigDecimal("-1.6").setScale(0, BigDecimal.ROUND_DOWN));    // -1
log.info("BigDecimal.ROUND_DOWN={}", new BigDecimal("-5.5").setScale(0, BigDecimal.ROUND_DOWN));    // -5
ROUND_CEILING
/**
 * Rounding mode to round towards positive infinity. If the BigDecimal is positive, behaves as for ROUND_UP; if negative, behaves as for ROUND_DOWN. 
 * Note that this rounding mode never decreases the calculated value.
 */
public final static int ROUND_CEILING = 2;

【说明】

该模式向正无穷四舍五入,是 ROUND_UP 和ROUND_DOWN 的组合,如果 BigDecimal 为正数,则行为与 ROUND_UP 相同;如果 BigDecimal 为负数,则行为与 ROUND_DOWN 相同。

log.info("BigDecimal.ROUND_CEILING={}", new BigDecimal("5.5").setScale(0, BigDecimal.ROUND_CEILING));     // 6
log.info("BigDecimal.ROUND_CEILING={}", new BigDecimal("1.6").setScale(0, BigDecimal.ROUND_CEILING));     // 2
log.info("BigDecimal.ROUND_CEILING={}", new BigDecimal("1.0").setScale(0, BigDecimal.ROUND_CEILING));     // 1
log.info("BigDecimal.ROUND_CEILING={}", new BigDecimal("-1.0").setScale(0, BigDecimal.ROUND_CEILING));    // -1
log.info("BigDecimal.ROUND_CEILING={}", new BigDecimal("-1.6").setScale(0, BigDecimal.ROUND_CEILING));    // -1
log.info("BigDecimal.ROUND_CEILING={}", new BigDecimal("-5.5").setScale(0, BigDecimal.ROUND_CEILING));    // -5
ROUND_FLOOR
/**
 * Rounding mode to round towards negative infinity. If the BigDecimal is positive, behave as for ROUND_DOWN; if negative, behave as for ROUND_UP. 
 * Note that this rounding mode never increases the calculated value.
 */
public final static int ROUND_FLOOR = 3;

【说明】

该模式向负无穷四舍五入,也是 ROUND_UP 和 ROUND_DOWN 的组合,但是和ROUND_CEILING 是相反的。如果 BigDecimal 为正数,则行为与 ROUND_DOWN 相同;如果为负数,则行为与 ROUND_UP 相同。

log.info("BigDecimal.ROUND_FLOOR={}", new BigDecimal("5.5").setScale(0, BigDecimal.ROUND_FLOOR));     // 5
log.info("BigDecimal.ROUND_FLOOR={}", new BigDecimal("1.6").setScale(0, BigDecimal.ROUND_FLOOR));     // 1
log.info("BigDecimal.ROUND_FLOOR={}", new BigDecimal("1.0").setScale(0, BigDecimal.ROUND_FLOOR));     // 1
log.info("BigDecimal.ROUND_FLOOR={}", new BigDecimal("-1.0").setScale(0, BigDecimal.ROUND_FLOOR));    // -1
log.info("BigDecimal.ROUND_FLOOR={}", new BigDecimal("-1.6").setScale(0, BigDecimal.ROUND_FLOOR));    // -2
log.info("BigDecimal.ROUND_FLOOR={}", new BigDecimal("-5.5").setScale(0, BigDecimal.ROUND_FLOOR));    // -6
ROUND_HALF_UP
/**
 * Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round up. 
 * Behaves as for ROUND_UP if the discarded fraction is ≥ 0.5; otherwise, behaves as for ROUND_DOWN. 
 * Note that this is the rounding mode that most of us were taught in grade school.
 */
public final static int ROUND_HALF_UP = 4;

【说明】

该模式向“最近的邻居”四舍五入。如果丢弃的分数是≥ 0.5,则行为与ROUND_UP相同;否则,行为与ROUND_DOWN相同。请注意,这是我们大多数人在小学时学过的舍入模式。

log.info("BigDecimal.ROUND_HALF_UP={}", new BigDecimal("5.5").setScale(0, BigDecimal.ROUND_HALF_UP));     // 6
log.info("BigDecimal.ROUND_HALF_UP={}", new BigDecimal("1.6").setScale(0, BigDecimal.ROUND_HALF_UP));     // 2
log.info("BigDecimal.ROUND_HALF_UP={}", new BigDecimal("1.0").setScale(0, BigDecimal.ROUND_HALF_UP));     // 1
log.info("BigDecimal.ROUND_HALF_UP={}", new BigDecimal("-1.0").setScale(0, BigDecimal.ROUND_HALF_UP));    // -1
log.info("BigDecimal.ROUND_HALF_UP={}", new BigDecimal("-1.6").setScale(0, BigDecimal.ROUND_HALF_UP));    // -2
log.info("BigDecimal.ROUND_HALF_UP={}", new BigDecimal("-5.5").setScale(0, BigDecimal.ROUND_HALF_UP));    // -6
ROUND_HALF_DOWN
/**
 * Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round down. 
 * Behaves as for ROUND_UP if the discarded fraction is > 0.5; otherwise, behaves as for ROUND_DOWN.
 */
public final static int ROUND_HALF_DOWN = 5;

【说明】

该模式向“最近的邻居”四舍五入。如果丢弃的分数是> 0.5,则行为与ROUND_UP相同;否则,行为与ROUND_DOWN相同,也就是五舍六入。

log.info("BigDecimal.ROUND_HALF_DOWN={}", new BigDecimal("5.5").setScale(0, BigDecimal.ROUND_HALF_DOWN));     // 5
log.info("BigDecimal.ROUND_HALF_DOWN={}", new BigDecimal("1.6").setScale(0, BigDecimal.ROUND_HALF_DOWN));     // 2
log.info("BigDecimal.ROUND_HALF_DOWN={}", new BigDecimal("1.0").setScale(0, BigDecimal.ROUND_HALF_DOWN));     // 1
log.info("BigDecimal.ROUND_HALF_DOWN={}", new BigDecimal("-1.0").setScale(0, BigDecimal.ROUND_HALF_DOWN));    // -1
log.info("BigDecimal.ROUND_HALF_DOWN={}", new BigDecimal("-1.6").setScale(0, BigDecimal.ROUND_HALF_DOWN));    // -2
log.info("BigDecimal.ROUND_HALF_DOWN={}", new BigDecimal("-5.5").setScale(0, BigDecimal.ROUND_HALF_DOWN));    // -5
ROUND_HALF_EVEN
/**
 * Rounding mode to round towards the "nearest neighbor" unless both neighbors are equidistant, in which case, round towards the even neighbor. 
 * Behaves as for ROUND_HALF_UP if the digit to the left of the discarded fraction is odd; behaves as for ROUND_HALF_DOWN if it's even. 
 * Note that this is the rounding mode that minimizes cumulative error when applied repeatedly over a sequence of calculations.
 */
public final static int ROUND_HALF_EVEN = 6;

【说明】

该模式是 ROUND_HALF_UP 和 ROUND_HALF_DOWN 的组合,但是比较特殊的是,如果被丢弃分数左边的数字是奇数,则行为与ROUND_HALF_UP(四舍五入)相同;如果是偶数,则表现为ROUND_HALF_DOWN(五舍六入)。请注意,在对一系列计算重复应用时,这种舍入模式可以最小化累积误差。

log.info("BigDecimal.ROUND_HALF_EVEN={}", new BigDecimal("5.5").setScale(0, BigDecimal.ROUND_HALF_EVEN));     // 6
log.info("BigDecimal.ROUND_HALF_EVEN={}", new BigDecimal("6.5").setScale(0, BigDecimal.ROUND_HALF_EVEN));     // 5
log.info("BigDecimal.ROUND_HALF_EVEN={}", new BigDecimal("1.6").setScale(0, BigDecimal.ROUND_HALF_EVEN));     // 2
log.info("BigDecimal.ROUND_HALF_EVEN={}", new BigDecimal("1.0").setScale(0, BigDecimal.ROUND_HALF_EVEN));     // 1
log.info("BigDecimal.ROUND_HALF_EVEN={}", new BigDecimal("-1.0").setScale(0, BigDecimal.ROUND_HALF_EVEN));    // -1
log.info("BigDecimal.ROUND_HALF_EVEN={}", new BigDecimal("-1.6").setScale(0, BigDecimal.ROUND_HALF_EVEN));    // -2
log.info("BigDecimal.ROUND_HALF_EVEN={}", new BigDecimal("-5.5").setScale(0, BigDecimal.ROUND_HALF_EVEN));    // -6
log.info("BigDecimal.ROUND_HALF_EVEN={}", new BigDecimal("-6.5").setScale(0, BigDecimal.ROUND_HALF_EVEN));    // -5
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 ArithmeticException is thrown.
 */ 
public final static int ROUND_UNNECESSARY = 7;

【说明】

该模式认为传入的数据一定满足设置的小数模式,因此不需要舍入。如果在产生不精确结果的操作上指定了此舍入模式,则会抛出ArithmeticException。

log.info("BigDecimal.ROUND_UNNECESSARY={}", new BigDecimal("5.5").setScale(0, BigDecimal.ROUND_UNNECESSARY));     // throw ArithmeticException
log.info("BigDecimal.ROUND_UNNECESSARY={}", new BigDecimal("1.6").setScale(0, BigDecimal.ROUND_UNNECESSARY));     // throw ArithmeticException
log.info("BigDecimal.ROUND_UNNECESSARY={}", new BigDecimal("1.0").setScale(0, BigDecimal.ROUND_UNNECESSARY));     // 1
log.info("BigDecimal.ROUND_UNNECESSARY={}", new BigDecimal("-1.0").setScale(0, BigDecimal.ROUND_UNNECESSARY));    // -1
log.info("BigDecimal.ROUND_UNNECESSARY={}", new BigDecimal("-1.6").setScale(0, BigDecimal.ROUND_UNNECESSARY));    // throw ArithmeticException
log.info("BigDecimal.ROUND_UNNECESSARY={}", new BigDecimal("-5.5").setScale(0, BigDecimal.ROUND_UNNECESSARY));    // throw ArithmeticException
三、BigDecimal 常用方法
  • add(BigDecimal augend)

返回 BigDecimal ,其值是 (this + augend) ,其标为 max(this.scale(), augend.scale())

  • subtract(BigDecimal subtrahend)

返回 BigDecimal ,其值是 (this - subtrahend) ,其标为 max(this.scale(), subtrahend.scale())

  • divide(BigDecimal divisor)

返回BigDecimal ,其值为(this / divisor) ,优先级为(this.scale() - divisor.scale()) ; 如果不能表示确切的商(因为它具有非终止的十进制扩展),则抛出一个ArithmeticException 。

  • divide(BigDecimal divisor, int roundingMode)

返回 BigDecimal ,其值是 (this / divisor) ,其标为 this.scale() 。

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

返回一个 BigDecimal ,其值为 (this / divisor) ,其比例为指定。

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

返回一个 BigDecimal ,其值为 (this / divisor) ,其比例为指定。

  • divide(BigDecimal divisor, RoundingMode roundingMode)

返回 BigDecimal ,其值是 (this / divisor) ,其标为 this.scale() 。

  • multiply(BigDecimal multiplicand)

返回 BigDecimal ,其值是 (this × multiplicand),其标为 (this.scale() + multiplicand.scale()) 。


版权声明:本文为CSDN博主「Unique Pursuer」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/LX2016341134/article/details/124476059?spm=1001.2014.3001.5502

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值