BigDecimal入门解析及实例讲解

1、BigDecimal介绍:


Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用

中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。


2、基本用法:


BigDecimal一共有4个构造方法
BigDecimal(int) 创建一个具有参数所指定整数值的对象。
BigDecimal(double) 创建一个具有参数所指定双精度值的对象。
BigDecimal(long) 创建一个具有参数所指定长整数值的对象。

BigDecimal(String) 创建一个具有参数所指定以字符串表示的数值的对象。


BigDecimal 的运算方式 不支持 + - * / 这类的运算 它有自己的运算方法


BigDecimal add(BigDecimal augend) 加法运算
BigDecimal subtract(BigDecimal subtrahend) 减法运算
BigDecimal multiply(BigDecimal multiplicand) 乘法运算

BigDecimal divide(BigDecimal divisor) 除法运算


3、举例说明为什么double和float类型无法处理精确数字:


System.out.println(0.01 + 0.06);     //打印结果:0.06999999999999999
System.out.println(1.0 - 0.32);       //打印结果:0.6799999999999999
System.out.println(2.01 * 100);      //打印结果:201.29999999999998
System.out.println(153.3/100);      //打印结果:1.5330000000000001


我们可以从代码结果发现打印结果都偏离正常值,这是因为计算机只识别二进制,但是二进制无法准确的描述十进制的0.07,当编译器读到0.07的时候,会找

一个最接近的值来代替,也就是:0.06999999999999999,所以我们需要使用BigDecimal 对象来操作。


4、举例说明BigDecimal可以处理精度问题

public class Test {
public static void main(String[] args) {

System.out.println(add(0.01, 0.06));  //打印结果:0.07

System.out.println(subtract(1.0, 0.32)); //打印结果:0.68

System.out.println(multiply(2.01, 100.0));//打印结果:201.000

System.out.println(divide(153.3, 100.0));//打印结果:1.533


}


public BigDecimal add(Double d1, Double d2) {

BigDecimal b1 = new BigDecimal(d1.toString());
BigDecimal b2 = new BigDecimal(d2.toString());

return b1.add(b2);

}


public BigDecimal subtract(Double d1, Double d2) {

BigDecimal b1 = new BigDecimal(d1.toString());
BigDecimal b2 = new BigDecimal(d2.toString());

return b1.subtract(b2);

}


public BigDecimal multiply(Double d1, Double d2) {

BigDecimal b1 = new BigDecimal(d1.toString());

BigDecimal b2 = new BigDecimal(d2.toString());

return b1.multiply(b2);

}


public BigDecimal divide(Double d1, Double d2) {

BigDecimal b1 = new BigDecimal(d1.toString());

BigDecimal b2 = new BigDecimal(d2.toString());

return b1.divide(b2);

}

}


5、使用舍入模式获取有效位数:


当我们在嫌弃1.533小数位过长,需要获取有效位时就需要使用到RoundingMode(舍入模式)。


RoundingMode在api中的解释: 为可能丢弃精度的数值操作指定一种舍入行为。每种舍入模式都指示如何计算返回舍入结果位数的最低有效位。如果返回的位

数比表示精确数值结果所需的位数少,则舍弃的位数称为舍弃部分,而不管这些位数对数值的作用如何。换句话说,假设是一个数值,舍弃部分的绝对值可能大于

 1。 (看着太啰嗦了,在接下来的实例中会详细介绍每个舍入模式的作用)


舍入模式的分类:

ROUND_UP:远离零方向舍入的舍入模式。(无论舍弃的非零数值是多少,前一位都加1)

实例:1.52 > 1.6, 1.58 > 1.6,-1.52 > -1.6 

ROUND_DOWN:向零方向舍入的舍入模式。(无论舍弃的数值是多少,前一位都不会增加数值)

实例:1.52 > 1.5, 1.58 > 1.5,-1.52 > -1.5 

ROUND_CEILING:向正无限大方向舍入的舍入模式。(如果是正数,和ROUND_UP效果一样,如果是负数,和ROUND_DOWN效果一样)

实例:1.52 > 1.6, -1.52 > -1.5

ROUND_FLOOR:向负无限大方向舍入的舍入模式。(和ROUND_CEILING相反)

实例:1.52 > 1.5 ,-1.52 > -1.6

ROUND_HALF_UP:向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向上舍入。(四舍五入)

实例:1.52 > 1.5, -1.55 > -1.6

ROUND_HALF_DOWN:向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向下舍入。(取六舍五)

    实例:1.55 > 1.5, 1.56 > 1.6

ROUND_HALF_EVEN: 向最接近数字方向舍入的舍入模式,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。

(如果舍弃部分的左边是奇数就和ROUND_HALF_UP一样,如果舍弃部分的左边是偶数就和ROUND_HALF_DOWN一样) 

实例: 1.25 > 1.2, 1.15 > 1.2

ROUND_UNNECESSARY:用于断言请求的操作具有精确结果的舍入模式,因此不需要舍入。 (使用舍入模式会抛ArithmeticException)


代码实现:

public static void main(String[] args) {

BigDecimal decimal = new BigDecimal("1.52");

// decimal.setScale(需要的有效位数, 舍入模式)
System.out.println("ROUND_UP的舍入模式 :  " + decimal.setScale(1,BigDecimal.ROUND_UP));

System.out.println("ROUND_DOWN的舍入模式:  " + decimal.setScale(1,BigDecimal.ROUND_DOWN));

System.out.println("ROUND_HALF_UP的舍入模式: " + decimal.setScale(1,BigDecimal.ROUND_HALF_UP));

System.out.println("ROUND_HALF_DOWN的舍入模式:" + decimal.setScale(1,BigDecimal.ROUND_HALF_DOWN));

System.out.println("ROUND_CEILING的舍入模式: " + decimal.setScale(1,BigDecimal.ROUND_CEILING));

System.out.println("ROUND_FLOOR的舍入模式: " + decimal.setScale(1,BigDecimal.ROUND_FLOOR));

System.out.println("ROUND_HALF_EVEN的舍入模式: " + decimal.setScale(1,BigDecimal.ROUND_HALF_EVEN));

System.out.println("ROUND_UNNECESSARY的舍入模式: " + decimal.setScale(1,BigDecimal.ROUND_UNNECESSARY));

}


打印结果:

ROUND_UP舍入模式:1.6
ROUND_DOWN舍入模式:1.5
ROUND_CEILING舍入模式:1.6
ROUND_FLOOR舍入模式:1.5
ROUND_HALF_UP舍入模式:1.5
ROUND_HALF_DOWN舍入模式:1.5
ROUND_HALF_EVEN舍入模式:1.5
Exception in thread "main" java.lang.ArithmeticException: Rounding necessary
at java.math.BigDecimal.divideAndRound(BigDecimal.java:1439)
at java.math.BigDecimal.setScale(BigDecimal.java:2390)
at demo.Test.main(Test.java:16)

如果大家有不同的意见或者建议,欢迎留言交流。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值