java BigDecimal 模式详解

java BigDecimal 模式详解

Java在java.math包中提供的API类BigDecimal,
用来对超过16位有效位的数进行精确的运算。

BigDecimal 是类似123.456这样的表示形式,
可以对数值进行切割,取舍,固定显示小数点后面几位,加减乘除等操作。

之前看了BigDecimal的使用,对BigDecimal里面的模式不是很清楚。

本文对BigDecimal中的模式进行详细介绍。

BigDecimal的模式是决定数值如何取舍

比如:

setScale方法,第一个参数表示保留小数点后面几位,第二个参数是模式值

BigDecimal.setScale(2,BigDecimal.ROUND_DOWN)      直接删除两位小数后面的小数, 1.235》1.23
BigDecimal.setScale(2,BigDecimal.ROUND_UP)        后面有数值,前面就要+1,     1.235》1.23
BigDecimal.setScale(2,BigDecimal.ROUND_HALF_UP)   四舍五入,向上取, 		1.235》1.24
BigDecimal.setScale(2,BigDecimal.ROUND_HALF_DOWN) 四舍五入,向下取, 		1.235》1.23  ,1.236》1.24

BigDecimal的模式是BigDecimal类中的静态值

有如下几个模式值:

public static final int ROUND_UP = 0;
public static final int ROUND_DOWN = 1;
public static final int ROUND_CEILING = 2;
public static final int ROUND_FLOOR = 3;
public static final int ROUND_HALF_UP = 4;
public static final int ROUND_HALF_DOWN = 5;
public static final int ROUND_HALF_EVEN = 6;
public static final int ROUND_UNNECESSARY = 7;

下面是所有模式值的详解

1、BigDecimal.ROUND_UP


oracle网页api中的解释翻译:
舍入模式从零舍入。始终在丢弃非零小数之前递增数字。注意,这种舍入模式永远不会减小计算值的大小。

但是和实际结果不同,查看类里面的说法和网页的也不一致,实际结果是绝对值比之前的大。
所以这里的计算值的大小的理解应该是不看正负的。


如下实际代码
	String TAG = "TAG"
        BigDecimal bigDecimal = new BigDecimal(1.234).setScale(2, BigDecimal.ROUND_UP);
        Log.i(TAG, "1.234 BigDecimal.ROUND_UP = " + bigDecimal);
        bigDecimal = new BigDecimal(-1.234).setScale(2, BigDecimal.ROUND_UP);
        Log.i(TAG, "-1.234 BigDecimal.ROUND_UP = " + bigDecimal);

运行结果:

	MainActivity: 1.234 BigDecimal.ROUND_UP = 1.24
	MainActivity: -1.234 BigDecimal.ROUND_UP = -1.24

分析:

正数好理解:1.24 比 1.234 大,所以 1.234 》1.24
负数,其实ROUND_UP是不管前面正负,只看小数部分0.24 比 0.234 大,所以-1.234 》-1.24
这里还有个没执行的情况:1.230 》1.23,因为这里只说没减少但是也不一定会增大
但是只有后面有值就会增,比如:1.230000001 》1.24

2、BigDecimal.ROUND_DOWN

oracle网页api中的解释翻译:
舍入模式向零舍入。切勿在舍弃小数(即截断)之前增加数字。请注意,此舍入模式永远不会增加计算值的大小。

这个是最好理解的,就是直接截断,不管后面的数值是啥


如下实际代码
	String TAG = "TAG"
        BigDecimal bigDecimal = new BigDecimal(1.234).setScale(2, BigDecimal.ROUND_DOWN);
        Log.i(TAG, "1.234 BigDecimal.ROUND_DOWN = " + bigDecimal);
        bigDecimal = new BigDecimal(-1.234).setScale(2, BigDecimal.ROUND_DOWN);
        Log.i(TAG, "-1.234 BigDecimal.ROUND_DOWN = " + bigDecimal);

运行结果:

	MainActivity: 1.234 BigDecimal.ROUND_DOWN = 1.23
	MainActivity: -1.234 BigDecimal.ROUND_DOWN = -1.23


3、BigDecimal.ROUND_CEILING

oracle网页api中的解释翻译:
舍入模式向正无穷大舍入。如果 BigDecimal为正,则表现为 ROUND_UP; 
如果为负,则行为与相同 ROUND_DOWN。请注意,此舍入模式永远不会减少计算值。

这个也不难理解,正数情况就舍进,负数情况就直接舍去。
CEILING翻译是天花板的意思。表示高。


如下实际代码
	String TAG = "TAG"
        BigDecimal bigDecimal = new BigDecimal(1.234).setScale(2, BigDecimal.ROUND_CEILING);
        Log.i(TAG, "1.234 BigDecimal.ROUND_CEILING = " + bigDecimal);
        bigDecimal = new BigDecimal(-1.234).setScale(2, BigDecimal.ROUND_CEILING);
        Log.i(TAG, "-1.234 BigDecimal.ROUND_CEILING = " + bigDecimal);

运行结果:

	MainActivity: 1.234 BigDecimal.ROUND_CEILING = 1.24
	MainActivity: -1.234 BigDecimal.ROUND_CEILING = -1.23

分析:
	1.24不小于1.234
	-1.23不小于-1.234
	同样也是不一定保证一定大,比如:1.230 》1.23

4、BigDecimal.ROUND_FLOOR

oracle网页api中的解释翻译:
舍入模式向负无穷大舍入。此舍入模式永远不会增加计算值。
如果 BigDecimal为正,则按ROUND_DOWN;的方式行事 。
如果为负,则表现为 ROUND_UP。请注意,


这个也不难理解,正数情况就舍去,负数情况就直接舍进。
FLOOR翻译是地板的意思。表示低。


如下实际代码
	String TAG = "TAG"
        BigDecimal bigDecimal = new BigDecimal(1.234).setScale(2, BigDecimal.ROUND_FLOOR);
        Log.i(TAG, "1.234 BigDecimal.ROUND_FLOOR = " + bigDecimal);
        bigDecimal = new BigDecimal(-1.234).setScale(2, BigDecimal.ROUND_FLOOR);
        Log.i(TAG, "-1.234 BigDecimal.ROUND_FLOOR = " + bigDecimal);

运行结果:

	MainActivity: 1.234 BigDecimal.ROUND_FLOOR = 1.23
	MainActivity: -1.234 BigDecimal.ROUND_FLOOR = -1.24
分析:
	1.23不大于1.234
	-1.24大大于-1.234
	同样:1.230 》1.23 ,-1.230 》-1.23
	

5、BigDecimal.ROUND_HALF_UP 四舍五入

oracle网页api中的解释翻译:
舍入模式向“最近的邻居”舍入,除非两个邻居都等距,在这种情况下将舍入。
表现为ROUND_UP丢弃分数是否≥0.5;否则,行为与相同ROUND_DOWN。

请注意,这是我们大多数人在小学时所教的四舍五入模式。
half翻译是一半的意思。
从字面翻译就是大于等于一半后舍入。

大部分情况都是使用这种模式。

如下实际代码
	String TAG = "TAG"
        BigDecimal bigDecimal = new BigDecimal(1.234).setScale(2, BigDecimal.ROUND_FLOOR);
        Log.i(TAG, "1.234 BigDecimal.ROUND_FLOOR = " + bigDecimal);
        bigDecimal = new BigDecimal(-1.234).setScale(2, BigDecimal.ROUND_FLOOR);
        Log.i(TAG, "-1.234 BigDecimal.ROUND_FLOOR = " + bigDecimal);

运行结果:

	MainActivity: 1.234 BigDecimal.ROUND_HALF_UP = 1.23
	MainActivity: -1.234 BigDecimal.ROUND_HALF_UP = -1.23
	MainActivity: 1.235 BigDecimal.ROUND_HALF_UP = 1.24
	MainActivity: -1.235 BigDecimal.ROUND_HALF_UP = -1.24
分析:
	这里的四舍五入也是不看正负的,只对绝对值有效。
	这个跟我们中学的是一样的,用的是靠近5原则,不管正负大小。

6、BigDecimal.ROUND_HALF_DOWN

oracle网页api中的解释翻译:
舍入模式向“最近的邻居”舍入,除非两个邻居都等距,在这种情况下舍入。行为ROUND_UP是否舍弃分数> 0.5;否则,行为与相同 ROUND_DOWN。

这种情况是一半也不舍入,要超过一半(6)才舍入



如下实际代码
	String TAG = "TAG"
        BigDecimal bigDecimal = new BigDecimal(1.234).setScale(2, BigDecimal.ROUND_FLOOR);
        Log.i(TAG, "1.234 BigDecimal.ROUND_FLOOR = " + bigDecimal);
        bigDecimal = new BigDecimal(-1.234).setScale(2, BigDecimal.ROUND_FLOOR);
        Log.i(TAG, "-1.234 BigDecimal.ROUND_FLOOR = " + bigDecimal);

运行结果:

	MainActivity: 1.234 BigDecimal.ROUND_HALF_DOWN = 1.23
	MainActivity: -1.234 BigDecimal.ROUND_HALF_DOWN = -1.23
	MainActivity: 1.235 BigDecimal.ROUND_HALF_DOWN = 1.24
	MainActivity: -1.235 BigDecimal.ROUND_HALF_DOWN = -1.24
	MainActivity: 1.236 BigDecimal.ROUND_HALF_DOWN = 1.24
	MainActivity: -1.236 BigDecimal.ROUND_HALF_DOWN = -1.24
分析:
	这个跟ROUND_HALF_UP类似,就是要以6为基准判断是否舍入舍去。

7、BigDecimal.ROUND_HALF_EVEN

oracle网页api中的解释翻译:
舍入模式向“最近的邻居”舍入,除非两个邻居都等距,则向相邻的偶数舍入。
如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同;
如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。
请注意,这是舍入模式,当在一系列计算中重复应用时,该模式可将累积误差最小化。

理解:
这个也是里面最难理解的一个。
就是要看舍弃的那位数值(<5)就舍去
舍弃的那位数值(>5)就舍进
如果刚好等于五,看前一位是奇数就舍进,偶数就舍去。

一句话:
即四舍六入五考虑,五后非零就进一,五后为零看奇偶,五前为偶应舍去,五前为奇要进一。

这种模式也是比较奇怪的,特殊场景才会用吧,网上把这个叫:银行家舍入




如下实际代码
	String TAG = "TAG"
        BigDecimal bigDecimal = new BigDecimal(1.234).setScale(2, BigDecimal.ROUND_HALF_EVEN);
        Log.i(TAG, "1.234 BigDecimal.ROUND_HALF_EVEN = " + bigDecimal);
        bigDecimal = new BigDecimal(-1.234).setScale(2, BigDecimal.ROUND_HALF_EVEN);
        Log.i(TAG, "-1.234 BigDecimal.ROUND_HALF_EVEN = " + bigDecimal);
        bigDecimal = new BigDecimal(1.235).setScale(2, BigDecimal.ROUND_HALF_EVEN);
        Log.i(TAG, "1.235 BigDecimal.ROUND_HALF_EVEN = " + bigDecimal);
        bigDecimal = new BigDecimal(-1.235).setScale(2, BigDecimal.ROUND_HALF_EVEN);
        Log.i(TAG, "-1.235 BigDecimal.ROUND_HALF_EVEN = " + bigDecimal);
        bigDecimal = new BigDecimal(1.245).setScale(2, BigDecimal.ROUND_HALF_EVEN);
        Log.i(TAG, "1.235 BigDecimal.ROUND_HALF_EVEN = " + bigDecimal);
        bigDecimal = new BigDecimal(-1.245).setScale(2, BigDecimal.ROUND_HALF_EVEN);
        Log.i(TAG, "-1.235 BigDecimal.ROUND_HALF_EVEN = " + bigDecimal);
        bigDecimal = new BigDecimal(1.236).setScale(2, BigDecimal.ROUND_HALF_EVEN);
        Log.i(TAG, "1.236 BigDecimal.ROUND_HALF_EVEN = " + bigDecimal);
        bigDecimal = new BigDecimal(-1.236).setScale(2, BigDecimal.ROUND_HALF_EVEN);
        Log.i(TAG, "-1.236 BigDecimal.ROUND_HALF_EVEN = " + bigDecimal);

运行结果:

	MainActivity: 1.234 BigDecimal.ROUND_HALF_EVEN = 1.23
	MainActivity: -1.234 BigDecimal.ROUND_HALF_EVEN = -1.23
	MainActivity: 1.235 BigDecimal.ROUND_HALF_EVEN = 1.24
	MainActivity: -1.235 BigDecimal.ROUND_HALF_EVEN = -1.24
	MainActivity: 1.245 BigDecimal.ROUND_HALF_EVEN = 1.24
	MainActivity: -1.245 BigDecimal.ROUND_HALF_EVEN = -1.24
	MainActivity: 1.236 BigDecimal.ROUND_HALF_EVEN = 1.24
	MainActivity: -1.236 BigDecimal.ROUND_HALF_EVEN = -1.24
分析:
	这里主要是看: 1.235 》1.245  ,5 前为奇数3,则舍进  , 
	1.245 》1.24 ,5 前为偶数4,则舍去 

8、BigDecimal.ROUND_UNNECESSARY

oracle网页api中的解释翻译:
舍入模式可以断言所请求的操作具有准确的结果,因此不需要舍入。如果在产生不精确结果的操作上指定了这种舍入模式,ArithmeticException则会引发an 。

这种是默认模式,但是有可能引发异常,不建议使用。
如果真要使用,应该是要配置其他参数的吧。



这个也是默认的值,网上说其他的值是默认,其实是不对的,源码如下:

    public BigDecimal setScale(int newScale) {
        return setScale(newScale, RoundingMode.UNNECESSARY);
    }



如下实际代码
	String TAG = "TAG"
        BigDecimal bigDecimal = new BigDecimal(1.234).setScale(2, BigDecimal.ROUND_UNNECESSARY);

运行结果:

	这个代码会运行异常,错误信息:Rounding necessary

但这里,BigDecimal的模式值就很详细的讲完了。

如果想详细看其他BigDecimal方法可以上官网看,或者下载api文档查看。
java1.8 api文档下载:https://download.csdn.net/download/wenzhi20102321/9619913
当然理解不透彻的地方,还是自己运行程序看是最容易理解的。

共勉:生活还是要主动点才能摄取。

发布了367 篇原创文章 · 获赞 1624 · 访问量 164万+

猜你喜欢

转载自blog.csdn.net/wenzhi20102321/article/details/104725470