文章内容
Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。
BigInteger 也可以存放比较大的数, 和 BigDecimal 的区别是 :BigInteger 存放的是大的整数,而BigDecimal 存放大的小数。
1、BigDecimal构造方法
BigDecimal一共有4个构造方法:
- BigDecimal(int) 创建一个具有参数所指定整数值的对象。
- BigDecimal(double) 创建一个具有参数所指定双精度值的对象。(不建议采用)
- BigDecimal(long) 创建一个具有参数所指定长整数值的对象。
- BigDecimal(String) 创建一个具有参数所指定以字符串表示的数值的对象。
实例化方法:
- BigDecimal BigDecimal(double d); //不允许使用
- BigDecimal BigDecimal(String s); //常用,推荐使用
- static BigDecimal valueOf(double d); //常用,推荐使用
注意:
- double 参数的构造方法,不允许使用,因为它不能精确的得到相应的值,值会变大;
- String 构造方法是完全可预知的: 写入 new BigDecimal(“0.1”) 将创建一个 BigDecimal,它正好等于预期的0.1; 因此,通常建议优先使用 String 构造方法;
- 静态方法 valueOf(double val) 内部实现,仍是将 double 类型转为 String 类型; 这通常是将 double(或float)转化为 BigDecimal 的首选方法。
BigDecimal 类的 valueOf()方法源码:
1 2 3 | public static BigDecimal valueOf( double val) { return new BigDecimal(Double.toString(val)); } |
2、BigDecimal格式化
由于NumberFormat类的format()方法可以使用BigDecimal对象作为其参数,可以利用BigDecimal对超出16位有效数字的货币值,百分值,以及一般数值进行格式化控制。 以利用BigDecimal对货币和百分比格式化为例。首先,创建BigDecimal对象,进行BigDecimal的算术运算后,分别建立对货币和百分比格式化的引用,最后利用BigDecimal对象作为format()方法的参数,输出其格式化的货币值和百分比 。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 | BigDecimal bigLoanAmount = new BigDecimal( "具体数值" ); //创建BigDecimal对象 BigDecimal bigInterestRate = new BigDecimal( "具体数值" ); BigDecimal bigInterest = bigLoanAmount.multiply(bigInterestRate); //BigDecimal运算 NumberFormat currency = NumberFormat.getCurrencyInstance(); //建立货币格式化引用 NumberFormat percent = NumberFormat.getPercentInstance(); //建立百分比格式化用 percent.setMaximumFractionDigits( 3 ); //百分比小数点最多3位 //利用BigDecimal对象作为参数在format()中调用货币和百分比格式化 System.out.println( "Loan amount:t" + currency.format(bigLoanAmount)); System.out.println( "Interest rate:t" + percent.format(bigInterestRate)); System.out.println( "Interest:t" + currency.format(bigInterest)); |
输出结果:
1 2 3 4 | Loan amount: ¥ 129 , 876 , 534 , 219 , 876 , 523.12 Interest rate: 8.765 % Interest: ¥ 11 , 384 , 239 , 549 , 149 , 661.69 |
常见用法:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 | 初始化 BigDecimal a= new BigDecimal( "1.35" ); 对数值取值: 1 .a.setScale( 1 ,BigDecimal.ROUND_DOWN); 取一位小数,直接删除后面多余位数,故取值 1.3 . 2 .a.setScale( 1 ,BigDecimal.ROUND_UP); 取一位小数,删除后面位数,进一位,故取值 1.4 . 3 .a.setScale( 1 ,BigDecimal.ROUND_HALF_UP); 取一位小数,四舍五入,故取值 1.4 . 4 .a.setScale( 1 ,BigDecimal.ROUND_HALF_DOWN); 取一位小数,五舍六入,故取值 1.3 . |
3、BigDecimal加减乘除运算
对于常用的加,减,乘,除,BigDecimal类提供了相应的成员方法 :
- public BigDecimal add(BigDecimal value); //加法
- public BigDecimal subtract(BigDecimal value); //减法
- public BigDecimal multiply(BigDecimal value); //乘法
- public BigDecimal divide(BigDecimal value); //除法
用法如下:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 | BigDecimal bignum1 = new BigDecimal( "10" ); BigDecimal bignum2 = new BigDecimal( "5" ); BigDecimal bignum3 = null ; //加法 bignum3 = bignum1.add(bignum2); System.out.println( "和 是:" + bignum3); //减法 bignum3 = bignum1.subtract(bignum2); System.out.println( "差 是:" + bignum3); //乘法 bignum3 = bignum1.multiply(bignum2); System.out.println( "积 是:" + bignum3); //除法 bignum3 = bignum1.divide(bignum2); System.out.println( "商 是:" + bignum3); |
注意:
BigDecimal除法可能出现不能整除的情况,比如 4.5/1.3,这时会报错java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result。
divide方法有可以传三个参数:public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) 第一参数表示除数, 第二个参数表示小数点后保留位数,第三个参数表示舍入模式,只有在作除法运算或四舍五入时才用到舍入模式,有下面这几种:

01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | ROUND_CEILING Rounding mode to round towards positive infinity. 向正无穷方向舍入 ROUND_DOWN Rounding mode to round towards zero. 向零方向舍入 ROUND_FLOOR Rounding mode to round towards negative infinity. 向负无穷方向舍入 ROUND_HALF_DOWN Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round down. 向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向下舍入, 例如1.55 保留一位小数结果为1.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. 向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,如果保留位数是奇数,使用ROUND_HALF_UP ,如果是偶数,使用ROUND_HALF_DOWN ROUND_HALF_UP Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round up. 向(距离)最近的一边舍入,除非两边(的距离)是相等,如果是这样,向上舍入, 1.55保留一位小数结果为1.6 ROUND_UNNECESSARY Rounding mode to assert that the requested operation has an exact result, hence no rounding is necessary. 计算结果是精确的,不需要舍入模式 ROUND_UP Rounding mode to round away from zero. 向远离0的方向舍入 |
4、BigDecimal 比较大小
BigDecimal使用compareTo方法比较大小:
1 2 3 4 5 6 7 8 9 | BigDecimal num1 = new BigDecimal( "0" ); BigDecimal num2 = new BigDecimal( "1" ); BigDecimal num3 = new BigDecimal( "2" ); BigDecimal num = new BigDecimal( "1" ); //用做比较的值 System.out.println(num1.compareTo(num)); //小于 时,返回 -1 System.out.println(num2.compareTo(num)); //等于 时,返回 0 System.out.println(num3.compareTo(num)); //大于 时,返回 1 |
5、其他常用方法
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 | /** * 求余数 * 返回值为 (this % divisor) 的 BigDecimal */ BigDecimal remainder(BigDecimal divisor); /** * 求相反数 * 返回值是 (-this) 的 BigDecimal */ BigDecimal negate(); /** * 将此 BigDecimal 与指定的 BigDecimal 比较 * 根据此方法,值相等但具有不同标度的两个 BigDecimal 对象(如,2.0 和 2.00)被认为是相等的; * 相对六个 boolean 比较运算符 (<, ==, >, >=, !=, <=) 中每一个运算符的各个方法,优先提供此方法; * 建议使用以下语句执行上述比较:(x.compareTo(y) <op> 0), 其中 <op> 是六个比较运算符之一; * * 指定者:接口 Comparable<BigDecimal> 中的 compareTo * 返回:当此 BigDecimal 在数字上小于、等于或大于 val 时,返回 -1、0 或 1 */ int compareTo(BigDecimal val); |