这节我们主要来说一说BigDecimal这个类,为啥要单独说这个类呢?因为后面学了数据库之后,我们会用到这个类。
一、认识BigDecimal
首先我们先百度百科一下(这个比较专业)
因为我写博客的日期是4月4号凌晨,这个图片啥的都变灰了,原因是这个
这里我也说一下, 很感谢国家,感谢这个社会,在疫情期间奋战在一线的工作人员,很感谢你们,谢谢。
“生如夏花般灿烂,死如秋叶之静美。”泰戈尔的话道出了生命的辉煌和壮丽。自古以来,赞颂生命的文人墨客数不胜数,每一个生命都是最珍贵最神圣的,因而我们应该学会敬畏生命。
哀悼完,我们继续来讲述BigDecimal这个类。
看百度百科中有这么一句话:“用来对超过16位有效位的数进行精确的运算。”
可以看出来啊,这个类还是很可以的啊,我之前项目就是用这个BigDecimal进行计算价格。
二、BigDecimal源码
打开API,地址:https://docs.oracle.com/javase/8/docs/api/
可以看到继承关系,BigDecimal继承了Number,Number继承了Object。然后我们打开Eclipse,我们创建一个类,然后输入BigDecimal,注意是java.math包下面的!!!我们点进去看一下源码
... 不好意思,我没有放源码包,算了,不看了,我们从API看吧
我们主要来看方法
它呢,给我们提供了很多方法,其中就有我们的加减乘除,我们来看一下
加法调用add,如下
减法调用subtract
乘法调用multiply
除法调用divide
我们发现,这个除法有很多重写的方法,这个我们会到时候说的。
三、BigDecimal的加减乘除等方法的使用
我们直接创建一个Test的类,我们来用用这个BigDecimal。
在使用之前,我们先定义两个数字,一个是5 一个是2
我们呢,选择这个构造函数进行定义
定义好之后,我们来进行计算
加法
首先计算number1 + number2,我们来使用一下add()这个方法。
我们传入一个要加的值 number2
输出一下
当然呢,加法计算,谁在前谁在后无所谓啊,你也可以number2.add(number1); 计算结果都是7.
减法
减法计算我们调用的是subtract,我们来讲add修改成subtract
我们运行,看一下结果
也是OK的,但是,减法存在减数和被减数,所以number2.subtract(number1); 结果是 -3
乘法
接下来是乘法,乘法我们用的是multiply,我们来算一下 number1 乘 number2的值
等于10,没有问题,当然,乘法和加法一样,不存在位置不一样得出的结果不一样,所以number2.multiply(number1);也是10
除法
除法我们用的是divide,这里我们要开始注意了,我们来计算number1 除 number2的值
2.5,没有问题,结果没有错,如果我们将2改成3 呢,我们再来看一下
报错了???,我们来解读一下错误日志,看看是啥错误
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
首先是这个Exception,这个异常是算术运算异常,具体的错误原因我们再来看一下
说是结果没有办法表示,的确,5除3的确除不开,这怎么办呢?
我们来看一下divide的其他重载方法。
我翻译了一圈,我是看着描述都差不多。我直接告诉大家用那一个。
public BigDecimal divide(BigDecimal divisor,int scale,int roundingMode)
就这个,我来解释一下参数,divisor就是你要除的内个数字,scale就是你要保留几个小数,roundingMode就是要按照哪种方法进行舍入,这里呢,BigDecimal提供了8中规则我们来介绍一下
public final static int ROUND_UP = 0;
舍入远离零的舍入模式。
在丢弃非零部分之前始终增加数字(始终对非零舍弃部分前面的数字加1)。
注意,此舍入模式始终不会减少计算值的大小。
解释:拿到一串数字,好比是10.005这个数字,如果保留两位小数,而且按照这个规则,我们可以得到10.01,为啥呢,原本我们要保留两位,最后的结果应该是10.00,但是,我们使用了规则之后,我们不管0.00 后面是几,都会进一位数字给十分位的。
public final static int ROUND_DOWN = 1;
接近零的舍入模式。
在丢弃某部分之前始终不增加数字(从不对舍弃部分前面的数字加1,即截短)。
注意,此舍入模式始终不会增加计算值的大小。
解释:就是,不管我们怎么保留,只保留到该保留的地方,剩下的直接舍去。我们再用10.001实验,保留两位数字,并且使用该模式,我们发现,不管是0.001 还是0.004,或者是0.009,我们最后都只能得到10.00。
public final static int ROUND_CEILING = 2;
接近正无穷大的舍入模式。
如果 BigDecimal 为正,则舍入行为与 ROUND_UP 相同;
如果为负,则舍入行为与 ROUND_DOWN 相同。
注意,此舍入模式始终不会减少计算值。
解释:这个就是结合上面内俩,看我们传入的是正数还是负数,这里我们直接测试。
我们通过测试发现,这个会保留比传入数字大的,不管是正数还是负数。
public final static int ROUND_FLOOR = 3;
接近负无穷大的舍入模式。
如果 BigDecimal 为正,则舍入行为与 ROUND_DOWN 相同;
如果为负,则舍入行为与 ROUND_UP 相同。
注意,此舍入模式始终不会增加计算值。
解释:正好与上面的ROUND_CEILING 相反
大家可以自己测试哦。
public final static int ROUND_HALF_UP = 4;
向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式。
如果舍弃部分 >= 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。
注意,这是我们大多数人在小学时就学过的舍入模式(四舍五入)。
解释:这个就是四舍五入,没有啥多解释的,我直接上测试结果。
public final static int ROUND_HALF_DOWN = 5;
向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为上舍入的舍入模式。
如果舍弃部分 > 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同(五舍六入)。
解释:这个就是五舍六入,小于或者等于5的时候,就舍弃掉,比5大就进位。看测试。
public final static int ROUND_HALF_EVEN = 6;
向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同;
如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。
注意,在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。
此舍入模式也称为“银行家舍入法”,主要在美国使用。四舍六入,五分两种情况。
如果前一位为奇数,则入位,否则舍去。
解释:我们好比要保留两位小数,我们看第三位小数位的数字是多少,如果小于或者等于4,就舍弃掉,如果第三位小数位的数字等于或者大于6,那么就进一位。
如果,第三位小数位的数字是5,则需要看它前一位是奇数还是偶数,如果是奇数,就进位,如果是偶数,则舍去。我们来测试
大家可以自己测试一下。
public final static int ROUND_UNNECESSARY = 7;
断言请求的操作具有精确的结果,因此不需要舍入。
如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。
解释:这个我是觉得没啥用,如果保留两位小数,但是我们要保留的小数有三位,好比10.001,这个一旦用了ROUND_UNNECESSARY这个规则,就报错,如果正好就两位,那么就没事,但是,我们本来就是两位小数,还保存两位小数,这不吃饱撑的吗。
到这里为止,除法就讲完了,具体用哪一种规则,需要看需求,由需求去定规则。
比较大小
我们呢,除去计算加减乘除之外,还可以比较大小,这里呢,我们也来使用一下。
我们调用compareTo()这个方法
我们不难看出,返回的是一个int,我们来看看这个int会输出什么
5和3比,输出了1
3 和 5 比,输出了-1
3 和 3比,输出了 0
这里我们可以知道,A和B比,如果A大,那么 compareTo 执行后的值是 1,如果是B大,则结果为-1,如果是结果是0,那么A和B相等。
好了,讲述到这里,我们BigDecimal就先告一段落了,大家要好好理解、记忆。
ps:这是我个人公众号,希望大家可以关注一下,我近期推出了活动,大家可以积极参加一下,奖品丰厚哦。
如有疑问,加我个人QQ:2100363119