Java中BigDecimal类型的舍入模式

一、简介

BigDecimaljava中用于高精度算术运算的。它是java.math包的一部分,提供了在商业计算中经常需要的精确控制舍入、精度、格式化以及算术运算的功能。BigDecimal 对浮点数进行了精确的表示,避免了 floatdouble 基本数据类型在表示、计算时可能出现的精度丢失问题。

二、舍入模式

2.1 新旧版舍入模式关系

java5舍入模式一般使用RoundingModeBigDecimal的舍入模式也仍然保留着,但在java11中使用该类的常量时,会提示过时。

RoundModeBigDecimal介绍
UPROUND_UP远离零方向舍入, 总是在丢弃非零分数之前增加数字,朝远离数轴的方向进位,正数+1,负数-1。(除保留位数后一位为0以外,其它不管正负号,直接进位)
DOWNROUND_DOWN向零方向舍入, 直接舍弃对应小数位后面的小数,不考虑任何进位
CEILINGROUND_CEILING向正无穷方向舍入。 对正数总是向上舍入(进位),对负数则舍去小数部分
FLOORROUND_FLOOR向负无穷方向舍入。 对正数舍去小数部分,对负数则向下舍入(进位)
HALF_UPROUND_HALF_UP四舍五入.。如果舍弃部分等于 0.5 或更大,则进位
HALF_DOWNROUND_HALF_DOWN五舍六入。 如果舍弃部分大于0.5,进位;等于 0.5 时不进位。
HALF_EVENROUND_HALF_EVEN银行家舍入法( 四舍六入五留双 )。 遇到0.5 时,舍入到最近的偶数。
UNNECESSARYROUND_UNNECESSARY具有精确的结果,因此不需要舍入。 如果在产生不精确结果的操作上指定了此舍入模式,则会抛出ArithmeticException。

2.2 使用示例

以保留两位小数为例。

2.2.1 RoundMode.UP

@Slf4j
public class DemoController {
    public static void main(String[] args) {
        log.info("original={} -> RoundingMode.UP={}", new BigDecimal("1.664"), new BigDecimal("1.664").setScale(2, RoundingMode.UP));
        log.info("original={} -> RoundingMode.UP={}", new BigDecimal("1.665"), new BigDecimal("1.665").setScale(2, RoundingMode.UP));
        log.info("original={} -> RoundingMode.UP={}", new BigDecimal("1.660"), new BigDecimal("1.660").setScale(2, RoundingMode.UP));
        log.info("original={} -> RoundingMode.UP={}", new BigDecimal("-1.660"), new BigDecimal("-1.660").setScale(2, RoundingMode.UP));
        log.info("original={} -> RoundingMode.UP={}", new BigDecimal("-1.665"), new BigDecimal("-1.665").setScale(2, RoundingMode.UP));
        log.info("original={} -> RoundingMode.UP={}", new BigDecimal("-1.664"), new BigDecimal("-1.664").setScale(2, RoundingMode.UP));
    }
}

结果如下, 丢弃的小数部分是 0(零分数),没有进位 :

original=1.666 -> RoundingMode.UP=1.67
original=1.665 -> RoundingMode.UP=1.67
original=1.660 -> RoundingMode.UP=1.66
original=-1.660 -> RoundingMode.UP=-1.66
original=-1.665 -> RoundingMode.UP=-1.67
original=-1.666 -> RoundingMode.UP=-1.67

2.2.2 RoundingMode.DOWN

@Slf4j
public class DemoController {
    public static void main(String[] args) {
        log.info("original={} -> RoundingMode.DOWN={}", new BigDecimal("1.664"), new BigDecimal("1.664").setScale(2, RoundingMode.DOWN));
        log.info("original={} -> RoundingMode.DOWN={}", new BigDecimal("1.665"), new BigDecimal("1.665").setScale(2, RoundingMode.DOWN));
        log.info("original={} -> RoundingMode.DOWN={}", new BigDecimal("1.660"), new BigDecimal("1.660").setScale(2, RoundingMode.DOWN));
        log.info("original={} -> RoundingMode.DOWN={}", new BigDecimal("-1.660"), new BigDecimal("-1.660").setScale(2, RoundingMode.DOWN));
        log.info("original={} -> RoundingMode.DOWN={}", new BigDecimal("-1.665"), new BigDecimal("-1.665").setScale(2, RoundingMode.DOWN));
        log.info("original={} -> RoundingMode.DOWN={}", new BigDecimal("-1.664"), new BigDecimal("-1.664").setScale(2, RoundingMode.DOWN));
    }
}

结果:

original=1.664 -> RoundingMode.DOWN=1.66
original=1.665 -> RoundingMode.DOWN=1.66
original=1.660 -> RoundingMode.DOWN=1.66
original=-1.660 -> RoundingMode.DOWN=-1.66
original=-1.665 -> RoundingMode.DOWN=-1.66
original=-1.664 -> RoundingMode.DOWN=-1.66

2.2.3 RoundingMode.CEILING

@Slf4j
public class DemoController {
    public static void main(String[] args) {
        log.info("original={} -> RoundingMode.CEILING={}", new BigDecimal("1.664"), new BigDecimal("1.664").setScale(2, RoundingMode.CEILING));
        log.info("original={} -> RoundingMode.CEILING={}", new BigDecimal("1.665"), new BigDecimal("1.665").setScale(2, RoundingMode.CEILING));
        log.info("original={} -> RoundingMode.CEILING={}", new BigDecimal("1.660"), new BigDecimal("1.660").setScale(2, RoundingMode.CEILING));
        log.info("original={} -> RoundingMode.CEILING={}", new BigDecimal("-1.660"), new BigDecimal("-1.660").setScale(2, RoundingMode.CEILING));
        log.info("original={} -> RoundingMode.CEILING={}", new BigDecimal("-1.665"), new BigDecimal("-1.665").setScale(2, RoundingMode.CEILING));
        log.info("original={} -> RoundingMode.CEILING={}", new BigDecimal("-1.664"), new BigDecimal("-1.664").setScale(2, RoundingMode.CEILING));
    }
}

结果如下,舍弃掉小数部分其实也算是增加值了。 如果小数部分为 0,则直接舍掉小数部分,不进行进位 :

original=1.664 -> RoundingMode.CEILING=1.67
original=1.665 -> RoundingMode.CEILING=1.67
original=1.660 -> RoundingMode.CEILING=1.66
original=-1.660 -> RoundingMode.CEILING=-1.66
original=-1.665 -> RoundingMode.CEILING=-1.66
original=-1.664 -> RoundingMode.CEILING=-1.66

2.2.4 RoundingMode.FLOOR

@Slf4j
public class DemoController {
    public static void main(String[] args) {
        log.info("original={} -> RoundingMode.FLOOR={}", new BigDecimal("1.664"), new BigDecimal("1.666").setScale(2, RoundingMode.FLOOR));
        log.info("original={} -> RoundingMode.FLOOR={}", new BigDecimal("1.665"), new BigDecimal("1.665").setScale(2, RoundingMode.FLOOR));
        log.info("original={} -> RoundingMode.FLOOR={}", new BigDecimal("1.660"), new BigDecimal("1.660").setScale(2, RoundingMode.FLOOR));
        log.info("original={} -> RoundingMode.FLOOR={}", new BigDecimal("-1.660"), new BigDecimal("-1.660").setScale(2, RoundingMode.FLOOR));
        log.info("original={} -> RoundingMode.FLOOR={}", new BigDecimal("-1.665"), new BigDecimal("-1.665").setScale(2, RoundingMode.FLOOR));
        log.info("original={} -> RoundingMode.FLOOR={}", new BigDecimal("-1.664"), new BigDecimal("-1.666").setScale(2, RoundingMode.FLOOR));
    }
}

结果如下:

original=1.664 -> RoundingMode.FLOOR=1.66
original=1.665 -> RoundingMode.FLOOR=1.66
original=1.660 -> RoundingMode.FLOOR=1.66
original=-1.660 -> RoundingMode.FLOOR=-1.66
original=-1.665 -> RoundingMode.FLOOR=-1.67
original=-1.664 -> RoundingMode.FLOOR=-1.67

2.2.5 RoundingMode.HALF_UP

@Slf4j
public class DemoController {
    public static void main(String[] args) {
        log.info("original={} -> RoundingMode.HALF_UP={}", new BigDecimal("1.664"), new BigDecimal("1.664").setScale(2, RoundingMode.HALF_UP));
        log.info("original={} -> RoundingMode.HALF_UP={}", new BigDecimal("1.665"), new BigDecimal("1.665").setScale(2, RoundingMode.HALF_UP));
        log.info("original={} -> RoundingMode.HALF_UP={}", new BigDecimal("1.660"), new BigDecimal("1.660").setScale(2, RoundingMode.HALF_UP));
        log.info("original={} -> RoundingMode.HALF_UP={}", new BigDecimal("-1.660"), new BigDecimal("-1.660").setScale(2, RoundingMode.HALF_UP));
        log.info("original={} -> RoundingMode.HALF_UP={}", new BigDecimal("-1.665"), new BigDecimal("-1.665").setScale(2, RoundingMode.HALF_UP));
        log.info("original={} -> RoundingMode.HALF_UP={}", new BigDecimal("-1.664"), new BigDecimal("-1.664").setScale(2, RoundingMode.HALF_UP));
    }
}

结果:

original=1.664 -> RoundingMode.HALF_UP=1.66
original=1.665 -> RoundingMode.HALF_UP=1.67
original=1.660 -> RoundingMode.HALF_UP=1.66
original=-1.660 -> RoundingMode.HALF_UP=-1.66
original=-1.665 -> RoundingMode.HALF_UP=-1.67
original=-1.664 -> RoundingMode.HALF_UP=-1.66

2.2.6 RoundingMode.HALF_DOWN

@Slf4j
public class DemoController {
    public static void main(String[] args) {
        log.info("original={} -> RoundingMode.HALF_DOWN={}", new BigDecimal("1.666"), new BigDecimal("1.666").setScale(2, RoundingMode.HALF_DOWN));
        log.info("original={} -> RoundingMode.HALF_DOWN={}", new BigDecimal("1.665"), new BigDecimal("1.665").setScale(2, RoundingMode.HALF_DOWN));
        log.info("original={} -> RoundingMode.HALF_DOWN={}", new BigDecimal("1.660"), new BigDecimal("1.660").setScale(2, RoundingMode.HALF_DOWN));
        log.info("original={} -> RoundingMode.HALF_DOWN={}", new BigDecimal("-1.660"), new BigDecimal("-1.660").setScale(2, RoundingMode.HALF_DOWN));
        log.info("original={} -> RoundingMode.HALF_DOWN={}", new BigDecimal("-1.665"), new BigDecimal("-1.665").setScale(2, RoundingMode.HALF_DOWN));
        log.info("original={} -> RoundingMode.HALF_DOWN={}", new BigDecimal("-1.666"), new BigDecimal("-1.666").setScale(2, RoundingMode.HALF_DOWN));
    }
}

结果:

original=1.666 -> RoundingMode.HALF_DOWN=1.67
original=1.665 -> RoundingMode.HALF_DOWN=1.66
original=1.660 -> RoundingMode.HALF_DOWN=1.66
original=-1.660 -> RoundingMode.HALF_DOWN=-1.66
original=-1.665 -> RoundingMode.HALF_DOWN=-1.66
original=-1.666 -> RoundingMode.HALF_DOWN=-1.67

2.2.7 RoundingMode.HALF_EVEN

规则:

  • 如果小数部分小于 0.5,直接舍去(向零方向)。
  • 如果小数部分大于0.5,向上舍入(远离零方向)。
  • 如果小数部分正好是0.5,则向最接近的偶数舍入。
@Slf4j
public class DemoController {
    public static void main(String[] args) {
        log.info("original={} -> RoundingMode.HALF_EVEN={}", new BigDecimal("1.654"), new BigDecimal("1.654").setScale(2, RoundingMode.HALF_EVEN));
        log.info("original={} -> RoundingMode.HALF_EVEN={}", new BigDecimal("1.656"), new BigDecimal("1.656").setScale(2, RoundingMode.HALF_EVEN));
        log.info("original={} -> RoundingMode.HALF_EVEN={}", new BigDecimal("1.655"), new BigDecimal("1.655").setScale(2, RoundingMode.HALF_EVEN));
        log.info("original={} -> RoundingMode.HALF_EVEN={}", new BigDecimal("1.675"), new BigDecimal("1.675").setScale(2, RoundingMode.HALF_EVEN));
        log.info("original={} -> RoundingMode.HALF_EVEN={}", new BigDecimal("1.660"), new BigDecimal("1.660").setScale(2, RoundingMode.HALF_EVEN));
        log.info("original={} -> RoundingMode.HALF_EVEN={}", new BigDecimal("-1.660"), new BigDecimal("-1.660").setScale(2, RoundingMode.HALF_EVEN));
        log.info("original={} -> RoundingMode.HALF_EVEN={}", new BigDecimal("-1.675"), new BigDecimal("-1.675").setScale(2, RoundingMode.HALF_EVEN));
        log.info("original={} -> RoundingMode.HALF_EVEN={}", new BigDecimal("-1.665"), new BigDecimal("-1.665").setScale(2, RoundingMode.HALF_EVEN));
        log.info("original={} -> RoundingMode.HALF_EVEN={}", new BigDecimal("-1.656"), new BigDecimal("-1.656").setScale(2, RoundingMode.HALF_EVEN));
        log.info("original={} -> RoundingMode.HALF_EVEN={}", new BigDecimal("-1.654"), new BigDecimal("-1.654").setScale(2, RoundingMode.HALF_EVEN));
    }
}

结果:

original=1.654 -> RoundingMode.HALF_EVEN=1.65
original=1.656 -> RoundingMode.HALF_EVEN=1.66
original=1.655 -> RoundingMode.HALF_EVEN=1.66
original=1.675 -> RoundingMode.HALF_EVEN=1.68
original=1.660 -> RoundingMode.HALF_EVEN=1.66
original=-1.660 -> RoundingMode.HALF_EVEN=-1.66
original=-1.675 -> RoundingMode.HALF_EVEN=-1.68
original=-1.665 -> RoundingMode.HALF_EVEN=-1.66
original=-1.656 -> RoundingMode.HALF_EVEN=-1.66
original=-1.654 -> RoundingMode.HALF_EVEN=-1.65

2.2.7 RoundingMode. UNNECESSARY

@Slf4j
public class DemoController {
    public static void main(String[] args) {
        log.info("original={} -> RoundingMode.UNNECESSARY={}", new BigDecimal("1.654"), new BigDecimal("1.654").setScale(2, RoundingMode.UNNECESSARY));
    }
}

结果:
image.png


那些照的我们无法睁眼的光,对我们其实只意味着黑暗。 – 梭罗

  • 23
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java,可以使用BigDecimal来对double类型进行四舍五入操作。具体方法如下: ```java import java.math.BigDecimal; public class TestRound { public static void main(String[] args) { double x = 3.1415926; BigDecimal bd = new BigDecimal(x); bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP); double result = bd.doubleValue(); System.out.println(result); } } ``` 在上述代码,我们创建了一个BigDecimal对象bd,并将其初始化为要进行四舍五入操作的double类型数值x。然后,我们通过调用setScale方法来设置保留的小数位数为2,并指定了四舍五入的模式为ROUND_HALF_UP。最后,我们通过调用doubleValue方法将BigDecimal对象转换回double类型,并将结果打印出来。 此外,还可以使用DecimalFormat类来格式化double类型的数值并进行四舍五入操作。具体方法如下: ```java import java.text.DecimalFormat; public class TestRound { public static void main(String[] args) { double x = 3.1415926; DecimalFormat df = new DecimalFormat("#.##"); df.setRoundingMode(RoundingMode.HALF_UP); String result = df.format(x); System.out.println(result); } } ``` 在上述代码,我们创建了一个DecimalFormat对象df,并指定了保留的小数位数为2,并将四舍五入模式设置为HALF_UP。然后,我们通过调用format方法将double类型的数值x格式化为字符串,并将结果打印出来。 综上所述,这两种方法都可以实现对double类型的四舍五入操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值