Java BigDecimal类及其示例
如果我们在需要精确值的Java应用程序中进行某些计算,例如在财务操作中,则不应使用float或者double基本类型。如果要存储非常大的数字,则采用相同的方法,例如,如果要计算阶乘,则长或者双精度可能会再次下降。在这种情况下,我们应该使用Java BigDecimal类代替,该类提供用于算术,缩放操作,舍入,比较,哈希和格式转换的操作。由于它是一个类,因此它的对象可以存储仅受计算机内存限制的很大的值,因此我们可以在BigDecimal类对象中存储大量的数字。
Java中的BigDecimal类还向用户提供了对舍入行为的完全控制,这是进行财务计算时的另一个常见要求。
让我们举个例子来看一下,如何使用float或者double可能会给我们带来错误的价值
double d1 = 78.95; double d2 = 67.55; System.out.println("d1 - d2= " + (d1-d2));
我们会期望输出为11.40,但是输出isd1 – d2 = 11.400000000000006
因此,我们可以看到一些近似值,而不是获得精确值。如果使用BigDecimals进行相同的计算,则将获得正确的值。
BigDecimal b1 = new BigDecimal("78.95"); BigDecimal b2 = new BigDecimal("67.55"); System.out.println("b1 - b2= " + b1.subtract(b2)); // b1 - b2= 11.40
Java BigDecimal构造函数
在Java BigDecimal类中,有许多构造函数,可以使用char [],int,double,long,String,BigDecimal初始化BigDecimal对象。以下是一些传递特定类型的构造函数
BigDecimal(char [] in)
BigDecimal(int val)
BigDecimal(字符串val)
有些构造函数会将MathContext实例与值一起作为第二个参数传递。以下是一些构造函数
BigDecimal(char [] in,MathContext mc)
BigDecimal(int val,MathContext mc)
BigDecimal(long val,MathContext mc)
MathContext实例封装了上下文设置,这些上下文描述描述了数值运算符的某些规则,例如精度设置,舍入模式
DECIMAL32 –一个MathContext对象,其精度设置为7位(与IEEE 754R Decimal32格式匹配),并且舍入模式为HALF_EVEN(默认为IEEE 754R)。
DECIMAL64 –一个MathContext对象,其精度设置为16位(与IEEE 754R Decimal64格式匹配)并且舍入模式为HALF_EVEN(默认为IEEE 754R)。
DECIMAL128 –一个MathContext对象,其精度设置为34位(与IEEE 754R Decimal128格式匹配)并且舍入模式为HALF_EVEN(默认为IEEE 754R)。
UNLIMITED –一个MathContext对象,其设置具有无限精度算术所需的值。
创建通过int和MathContext的BigDecimal实例的示例。
BigDecimal b1 = new BigDecimal(6, MathContext.DECIMAL64);
还有一些构造函数可以将scale作为参数传递,并同时传递scale和MathContext实例。
BigDecimal(BigInteger unscaledVal,int scale)
BigDecimal(BigInteger unscaledVal,int scale,MathContext mc)
这是一个传递BigInteger实例和小数位数以创建BigDecimal实例的示例。
BigInteger bi = new BigInteger("4567898"); int scale = 2; BigDecimal bd = new BigDecimal(bi, scale); System.out.println(bd); // 45678.98
BigDecimal中的舍入模式
Java BigDecimal类的一项便利功能是传递舍入模式,该模式指定数字运算的舍入行为。 RoundingMode是包java.math中提供的Enum,它提供以下Enum常量。
CEILING–取整模式可以向正无穷大取整。
DOWN–舍入模式将舍入为零。
FLOOR –取整模式,取整为负无穷大。
HALF_DOWN –舍入模式向"最近的邻居"舍入,除非两个邻居都等距,在这种情况下舍入。
HALF_EVEN –舍入模式向"最近的邻居"舍入,除非两个邻居都等距,在这种情况下,向偶数邻居舍入。
HALF_UP –舍入模式向"最近的邻居"舍入,除非两个邻居等距。
UNNECESSARY-舍入模式可以断言所请求的操作具有准确的结果,因此不需要舍入。
UP–舍入模式从零舍入。
这是一个汇总表,显示了所有舍入模式下这些舍入运算的结果。
输入数字 | UP | DOWN | CEILING | FLOOR | HALF_UP | HALF_DOWN | HALF_EVEN | UNNECESSARY |
---|---|---|---|---|---|---|---|---|
5.5 | 6 | 5 | 6 | 5 | 6 | 抛出算术异常 | ||
2.5 | 3 | 2 | 3 | 2 | 2 | 抛出算术异常 | ||
1.6 | 2 | 1 | 2 | 2 | 抛出算术异常 | |||
1.1 | 2 | 1 | 2 | 1 | 1 | 抛出算术异常 | ||
1.0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
-1.0 | -1 | -1 | -1 | -1 | -1 | -1 | -1 | -1 |
-1.1 | -2 | -1 | -1 | -2 | -1 | -1 | -1 | 抛出算术异常 |
-1.6 | -2 | -1 | -1 | -2 | -2 | -2 | 抛出算术异常 | |
-2.5 | -3 | -2 | -2 | -3 | -3 | -2 | -2 | 抛出算术异常 |
-5.5 | -6 | -5 | -5 | -6 | -6 | -5 | -6 | 抛出算术异常 |
Java BigDecimal中的缩放方法
提供小数位数(小数点后的位数)和舍入模式的方法可能是BigDecimal类中最常用的方法。
setScale(int newScale)–返回一个BigDecimal,其小数位数是指定值,并且其数值在数值上等于该BigDecimal的数值。
setScale(int newScale,RoundingMode roundingMode)–设置缩放和舍入模式的方法。
BigDecimal bd = new BigDecimal("4567.876"); System.out.println("BigDecimal- " + bd); System.out.println("BigDecimal(RoundingMode.DOWN)- " + bd.setScale(2, RoundingMode.DOWN)); System.out.println("BigDecimal(RoundingMode.CEILING)- " + bd.setScale(2, RoundingMode.CEILING)); System.out.println("BigDecimal(RoundingMode.FLOOR)- " + bd.setScale(2, RoundingMode.FLOOR)); System.out.println("BigDecimal(RoundingMode.HALF_DOWN)- " + bd.setScale(2, RoundingMode.HALF_DOWN)); System.out.println("BigDecimal(RoundingMode.HALF_EVEN)- " + bd.setScale(2, RoundingMode.HALF_EVEN));
输出:
BigDecimal- 4567.876 BigDecimal(RoundingMode.DOWN)- 4567.87 BigDecimal(RoundingMode.CEILING)- 4567.88 BigDecimal(RoundingMode.FLOOR)- 4567.87 BigDecimal(RoundingMode.HALF_DOWN)- 4567.88 BigDecimal(RoundingMode.HALF_EVEN)- 4567.88
BigDecimal方法示例
让我们看一下Java BigDecimal类中用于执行算术运算的其他一些方法的示例。
- Java对象中不允许使用算术运算符(+,-,*,/),因此这些运算符也不能与BigDecimal实例一起使用。 BigDecimal类中有加,减,乘和除的方法来执行这些算术运算。
add(BigDecimal bd2)–返回其值为(this + bd2)的BigDecimal。
split(BigDecimal divisor)–返回其值为(this / divisor)的BigDecimal。
除法(BigDecimal除数,整数刻度,RoundingMode roundingMode)-返回一个BigDecimal,其值为(this / divisor),其刻度已指定。
乘法(BigDecimal bd2)-返回一个BigDecimal,其值为(this×bd2)
减法(BigDecimal bd2)–返回其值为(this – bd2)的BigDecimal。
public class BDDemo { public static void main(String[] args) throws IOException { BigDecimal bd1 = new BigDecimal("4567.876"); BigDecimal bd2 = new BigDecimal(4000.676); System.out.println("BigDecimal addition- " + bd1.add(bd2).setScale(2, RoundingMode.HALF_EVEN)); System.out.println("BigDecimal subtraction- " + bd1.subtract(bd2).setScale(2, RoundingMode.HALF_EVEN)); System.out.println("BigDecimal multiplication)- " + bd1.multiply(bd2).setScale(2, RoundingMode.HALF_EVEN)); System.out.println("BigDecimal division- " + bd1.divide(bd2, 2, RoundingMode.HALF_EVEN)); } }
输出:
BigDecimal addition- 8568.55 BigDecimal subtraction- 567.20 BigDecimal multiplication)- 18274591.88 BigDecimal division- 1.14
- BigDecimal中的max和min方法
max(BigDecimal val)–返回此BigDecimal和val的最大值。
min(BigDecimal val)–返回此BigDecimal和val的最小值。
BigDecimal bd1 = new BigDecimal("4567.876"); BigDecimal bd2 = new BigDecimal("4000.676"); System.out.println("Max BigDecimal- " + bd1.max(bd2)); System.out.println("Min BigDecimal- " + bd1.min(bd2));
输出:
Max BigDecimal- 4567.876 Min BigDecimal- 4000.676
- BigDecimal中的Pow方法
- pow(int n)-返回BigDecimal,其值为(this n)。
BigDecimal bd = new BigDecimal("45"); System.out.println("45^4- " + bd.pow(4)); // 4100625
比较两个BigDecimals
尽管为了检查对象是否相等,我们将使用equals方法,但是此方法不适用于BigDecimal数字,因为此方法仅在两个BigDecimal对象的值和小数均相等时才认为它们相等,因此,如果equals方法为5.0,则5.0不等于5.00用过的。
为了比较BigDecimals,使用compareTo()方法。
- compareTo(BigDecimal val)–将此BigDecimal与指定的BigDecimal进行比较。此方法将值相等但规模不同(例如2.0和2.00)的两个BigDecimal对象视为相等。如果小于val,则返回-1. 如果两者相等,则为0。如果大于val,则为1.
BigDecimal bd1 = new BigDecimal("5.00"); BigDecimal bd2 = new BigDecimal("5.0"); System.out.println("bd1 equals bd2 - " + bd1.equals(bd2)); System.out.println("bd1 compare to bd2 - " + bd1.compareTo(bd2));
输出:
bd1 equals bd2 - false bd1 compare to bd2 - 0