对于用过BigDecimal的人来说,一定遇到过MathContext这个对象吧?我遇到的时候也是一脸懵逼,为了搞清楚什么是MathContext我查了很多的书籍,也看了很多的博客,发现想搞懂MathContext还必须先搞懂RoundingMode,于是我又不得不查RoundingMode的相关。现在大致有了一点眉目。下面就简单说一下,希望对大家能有所帮助。
RoundingMode
对于RoundingMode来说,大概就是对舍入模式的抽象。这是一个枚举类,点开源码后可以发现声明了如下的几个枚举值:
-
UP(BigDecimal.ROUND_UP):直接进位处理
关于UP的测试代码如下:
public class RoundingModeTest{
public static void main(String[] args) {
BigDecimal b = BigDecimal.valueOf(12.3459);
BigDecimal b2 = BigDecimal.valueOf(12.3451);
BigDecimal b3 = BigDecimal.valueOf(12.3455);
System.out.println("采用Rounding.UP得到的结果:" + b.setScale(3, RoundingMode.UP));
System.out.println("采用Rounding.UP得到的结果:" + b2.setScale(3, RoundingMode.UP));
System.out.println("采用Rounding.UP得到的结果:" + b3.setScale(3, RoundingMode.UP));
}
}
执行结果如下图所示:
-
DOWN(BigDecimal.ROUND_DOWN):舍弃不需要的小数位
示例代码如下所示:
public class RoundingModeTest{
public static void main(String[] args) {
BigDecimal b = BigDecimal.valueOf(12.3459);
BigDecimal b2 = BigDecimal.valueOf(12.3451);
BigDecimal b3 = BigDecimal.valueOf(12.3455);
System.out.println("采用Rounding.DOWN得到的结果:" + b.setScale(3, RoundingMode.DOWN));
System.out.println("采用Rounding.DOWN得到的结果:" + b2.setScale(3, RoundingMode.DOWN));
System.out.println("采用Rounding.DOWN得到的结果:" + b3.setScale(3, RoundingMode.DOWN));
}
}
执行结果如下图所示:
-
CEILING(BigDecimal.ROUND_CEILING):舍去不需要的小数位,再最后一位进1
示例代码如下所示:
public class RoundingModeTest{
public static void main(String[] args) {
BigDecimal b = BigDecimal.valueOf(12.3459);
BigDecimal b2 = BigDecimal.valueOf(12.3451);
BigDecimal b3 = BigDecimal.valueOf(12.3455);
System.out.println("采用Rounding.CEILING得到的结果:" + b.setScale(3, RoundingMode.CEILING));
System.out.println("采用Rounding.CEILING得到的结果:" + b2.setScale(3, RoundingMode.CEILING));
System.out.println("采用Rounding.CEILING得到的结果:" + b3.setScale(3, RoundingMode.CEILING));
}
}
执行结果如下图所示:
-
FLOOR(BigDecimal.ROUND_FLOOR):直接舍去不需要的小数位
示例代码如下所示:
public class RoundingModeTest{
public static void main(String[] args) {
BigDecimal b = BigDecimal.valueOf(12.3459);
BigDecimal b2 = BigDecimal.valueOf(12.3451);
BigDecimal b3 = BigDecimal.valueOf(12.3455);
System.out.println("采用Rounding.FLOOR得到的结果:" + b.setScale(3, RoundingMode.FLOOR));
System.out.println("采用Rounding.FLOOR得到的结果:" + b2.setScale(3, RoundingMode.FLOOR));
System.out.println("采用Rounding.FLOOR得到的结果:" + b3.setScale(3, RoundingMode.FLOOR));
}
}
执行结果如下图所示:
-
HALF_UP(BigDecimal.ROUND_HALF_UP):舍去不需要的小数位,向保留小数位最近的数字靠近。距离相等时,直接舍去小数位,在现有保留小数位的最低位加1.
示例代码如下所示:
public class RoundingModeTest{
public static void main(String[] args) {
BigDecimal b = BigDecimal.valueOf(12.3459);
BigDecimal b2 = BigDecimal.valueOf(12.3451);
BigDecimal b3 = BigDecimal.valueOf(12.3455);
System.out.println("采用Rounding.HALF_UP得到的结果:" + b.setScale(3, RoundingMode.HALF_UP));
System.out.println("采用Rounding.HALF_UP得到的结果:" + b2.setScale(3, RoundingMode.HALF_UP));
System.out.println("采用Rounding.HALF_UP得到的结果:" + b3.setScale(3, RoundingMode.HALF_UP));
}
}
执行结果如下图所示:
-
HALF_DOWN(BigDecimal.ROUND_HALF_DOWN):舍去不需要的小数位,向保留小数位最近的数字靠近。距离相等时,直接舍去小数位。
示例代码如下所示:
public class RoundingModeTest {
public static void main(String[] args) {
BigDecimal b = BigDecimal.valueOf(12.3459);
BigDecimal b2 = BigDecimal.valueOf(12.3451);
BigDecimal b3 = BigDecimal.valueOf(12.3455);
System.out.println("采用Rounding.HALF_DOWN得到的结果:" + b.setScale(3, RoundingMode.HALF_DOWN));
System.out.println("采用Rounding.HALF_DOWN得到的结果:" + b2.setScale(3, RoundingMode.HALF_DOWN));
System.out.println("采用Rounding.HALF_DOWN得到的结果:" + b3.setScale(3, RoundingMode.HALF_DOWN));
}
}
执行结果如下图与所示:
-
HALF_EVEN(BigDecimal.ROUND_HALF_EVEN)::舍去不需要的小数位,向保留小数位最近的数字靠近。距离相等时,向现有保留小数位的最低位是偶数的靠近。
示例代码如下所示:
public class RoundingModeTest{
public static void main(String[] args) {
BigDecimal b = BigDecimal.valueOf(12.3459);
BigDecimal b2 = BigDecimal.valueOf(12.3451);
BigDecimal b3 = BigDecimal.valueOf(12.3455);
BigDecimal b4 = BigDecimal.valueOf(12.3445);
System.out.println("采用Rounding.HALF_EVEN得到的结果:" + b.setScale(3, RoundingMode.HALF_EVEN));
System.out.println("采用Rounding.HALF_EVEN得到的结果:" + b2.setScale(3, RoundingMode.HALF_EVEN));
System.out.println("采用Rounding.HALF_EVEN得到的结果:" + b3.setScale(3, RoundingMode.HALF_EVEN));
System.out.println("采用Rounding.HALF_EVEN得到的结果:" + b4.setScale(3, RoundingMode.HALF_EVEN));
}
}
执行结果如下图所示:
-
UNNECESSARY(BigDecimal.ROUND_UNNECESSARY):不需要舍入
对于该模式来说,如果要求保留位数小于实际位数则会抛出算术异常。
仔细观察后发现,RoundingMode其实就是对BigDecimal中各种舍入常量值的封装。当然,单独讨论RoundingMode是没有任何意义的,它需要和MathContext配合使用。
MathContext
对于MathContext类来说,我就简单粗暴的称为数学上下文吧。因为我英语是个二把刀。MathContext所做的事就是封装舍入模式对象RoundingMode和处理位数precision。
MathContext的构造器有三个:
-
public MathContext(int setPrecision):传入所占位数
-
public MathContext(int setPrecision, RoundingMode setRoundingMode):传入所占位数和舍入模式
-
public MathContext(String val):传入字符串,需要说明的是,该字符串必须是另一个MathContext对象调用toString方法后得到的字符串。
示例代码如下所示:
public class MathContextTest {
public static void main(String[] args) {
MathContext mc1 = new MathContext(12);
MathContext mc2 = new MathContext(13, RoundingMode.FLOOR);
MathContext mc3 = new MathContext(mc1.toString());
}
}
对于MathContext来说常用的方法有:
-
public int getPrecision():获取所占位数
-
public RoundingMode getRoundingMode():获取舍入模式
-
public java.lang.String toString():转换为字符串
示例代码如下所示:
public class MathContextTest {
public static void main(String[] args) {
MathContext mc = new MathContext(13, RoundingMode.FLOOR);
System.out.println("mc的precision:" + mc.getPrecision());
System.out.println("mc的RoundingMode:" + mc.getRoundingMode());
}
}
执行结果如下图所示:
与RoundingMode一样,单独讨论MathContext也没有太大的意义,主要是配合BigDecimal来进行使用。关于MathContext和RoundingMode的介绍就说这么多。