BigDecimal 详解

BigDecimal 详解

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

BigDecimal表示功能强大小数的意思,Decimal翻译是小数的。

BigDecimal所创建的是对象,故我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。

一、BigDecimal的作用:

1、能对数据小数部分保留小数后面固定位数,并且进行不同模式的舍去操作
2、对数据进行加减乘除等数据操作
3、能判断该数值的位数(小数点前后的),数值的小数位数
4、两个数值进行比较

二、BigDecimal常用构造函数和相关类

1、传入基本数据类型数据或者数据字符串

BigDecimal(int|double|long|char[]|String in)

如下代码:

    BigDecimal bigDecimal = new BigDecimal("123.456");
    System.out.println("bigDecimal 123.456 string =" + bigDecimal);
    bigDecimal = new BigDecimal(123.456);
    System.out.println("bigDecimal 123.456 float =" + bigDecimal);
    bigDecimal = new BigDecimal(123);
    System.out.println("bigDecimal 123 int =" + bigDecimal);

运行结果:

    bigDecimal 123.456 string =123.456
    bigDecimal 123.456 float =123.4560000000000030695446184836328029632568359375
    bigDecimal 123 int =123

由此可以看出,BigDecimal对象,如果有小数的情况,
如果不对小数位数进行控制,小数后面的位数是不可控的。

2、传入基本数据类型数据或者数据字符串、限制规则对象

BigDecimal(int|double|long|char[]|String in, MathContext mc)

其中MathContext是一个数据规则对象,可以该数值显示的最多位数和四舍五入规则。
比如:MathContext mc = new MathContext(5, RoundingMode.HALF_UP);
第一个参数表示,该数值最多显示的位数,
第二个参数表示,改数值舍入舍出的模式,RoundingMode.HALF_UP表示四舍五入,RoundingMode.DOWN表示舍去
数值舍入舍出的模式还有其他六种模式,详情请看:https://blog.csdn.net/wenzhi20102321/article/details/104725470

如下代码:

    MathContext mc = new MathContext(5, RoundingMode.HALF_UP);
    BigDecimal bigDecimal = new BigDecimal("123.456", mc);
    System.out.println("bigDecimal 123.456 string =" + bigDecimal);
    bigDecimal = new BigDecimal(123.456, mc);
    System.out.println("bigDecimal 123.456 float =" + bigDecimal);
    bigDecimal = new BigDecimal(123, mc);
    System.out.println("bigDecimal 123 int =" + bigDecimal);

运行结果:

    bigDecimal 123.456 string =123.46
    bigDecimal 123.456 float =123.46
    bigDecimal 123 int =123

如果规则对象修改为如下:

MathContext mc = new MathContext(2, RoundingMode.HALF_UP);

运行结果:

    bigDecimal 123.456 string =1.2E+2
    bigDecimal 123.456 float =1.2E+2
    bigDecimal 123 int =1.2E+2

上面是科学计数法,表示1.2乘以10的两次方。

BigDecimal方法也是可以通过方法setScale(int scale, int roundingMode)
设置小数点后面位数和控制舍入舍出模式

4、其他构造方法


BigDecimal(BigInteger val)
BigDecimal(char[] in, int offset, int len)
BigDecimal(BigInteger unscaledVal, int scale, MathContext mc)

三、BigDecimal常用方法详解

1、add(BigDecimal)相加

BigDecimal对象中的值相加,返回BigDecimal对象

2、subtract(BigDecimal)相减

BigDecimal对象中的值相减,返回BigDecimal对象

3、multiply(BigDecimal)相乘

BigDecimal对象中的值相乘,返回BigDecimal对象

4、divide(BigDecimal)相除

BigDecimal对象中的值相除,返回BigDecimal对象

5、toString(),doubleValue(),floatValue(),longValue(),intValue()

将BigDecimal对象中的值转换对应类型数据

6、大小比较compareTo(BigDecimal)

int a = bigdemical.compareTo(bigdemical2)
返回结果分析:
a = -1,表示bigdemical小于bigdemical2;
a = 0,表示bigdemical等于bigdemical2;
a = 1,表示bigdemical大于bigdemical2;

7、setScale(int newScale, int roundingMode)设置精度

第一个参数newScale表示设置小数点后面几位数,如果不够就补零,要舍弃就按后面的规则处理
第二个参数roundingMode,表示舍入舍出模式值,RoundingMode.HALF_UP表示四舍五入,RoundingMode.DOWN表示舍去

代码:

    BigDecimal bigDecimal = new BigDecimal("123.456").setScale(2, BigDecimal.ROUND_HALF_UP); //四舍五入
    System.out.println("bigDecimal 123.456 string =" + bigDecimal);
    bigDecimal = new BigDecimal(123.456).setScale(2, BigDecimal.ROUND_DOWN); //直接舍去
    System.out.println("bigDecimal 123.456 float =" + bigDecimal);
    bigDecimal = new BigDecimal(123).setScale(2, BigDecimal.ROUND_HALF_UP);
    System.out.println("bigDecimal 123 int =" + bigDecimal);

运行结果:

    bigDecimal 123.456 string =123.46
    bigDecimal 123.456 float =123.45
    bigDecimal 123 int =123.00

setScale方法在BigDecimal还是比较重要的,因为小数默认是有很多位的,
如果不进行精度设置显示小数位数是不确定的。
setScale还有包含设置数据规则对象的参数方法:

setScale(int newScale, RoundingMode roundingMode)

8、precision()精度获取,scale()小数位数获取

如下代码:

    BigDecimal bigDecimal = new BigDecimal(123).setScale(2, BigDecimal.ROUND_HALF_UP);
    System.out.println("bigDecimal 123 int setScale 2 =" + bigDecimal);
    System.out.println("bigDecimal 123 precision =" + bigDecimal.precision());
    System.out.println("bigDecimal 123 scale =" + bigDecimal.scale());
    bigDecimal = new BigDecimal(123.456);
    System.out.println("bigDecimal 123.456 float setScale 2 =" + bigDecimal);
    System.out.println("bigDecimal 123.456 precision =" + bigDecimal.precision());
    System.out.println("bigDecimal 123.456 scale =" + bigDecimal.scale());
    bigDecimal = new BigDecimal(0.456);
    System.out.println("bigDecimal 123.456 float =" + bigDecimal);
    System.out.println("bigDecimal 123.456 precision =" + bigDecimal.precision());
    System.out.println("bigDecimal 123.456 scale =" + bigDecimal.scale());
    bigDecimal = new BigDecimal(0.45600);
    System.out.println("bigDecimal 0.45600 float =" + bigDecimal);
    System.out.println("bigDecimal 0.45600 precision =" + bigDecimal.precision());
    System.out.println("bigDecimal 0.45600 scale =" + bigDecimal.scale());

运行结果:

    bigDecimal 123 int setScale 2 =123.00
    bigDecimal 123 precision =5
    bigDecimal 123 scale =2
    bigDecimal 123.456 float =123.4560000000000030695446184836328029632568359375
    bigDecimal 123.456 precision =49
    bigDecimal 123.456 scale =46
    bigDecimal 123.456 float =0.456000000000000016431300764452316798269748687744140625
    bigDecimal 123.456 precision =54
    bigDecimal 123.456 scale =54
    bigDecimal 0.45600 float =0.456000000000000016431300764452316798269748687744140625
    bigDecimal 0.45600 precision =54
    bigDecimal 0.45600 scale =54

分析:

1、precision()方法是获取小数点前后数值的位数,但是整数是零的情况,整数位不算入内。
2、scale()方法是获取数值小数的位数,不进行小数位设置的情况,获取的值是不定的。
3、precision() - scale() 即可获取整数的位数,如果小于等于0,表示个位为零,并且该数值不大于1。

8、divideAndRemainder(BigDecimal divisor) 求商和求余

divideAndRemainder方法的结果是一个BigDecimal数组,
第一个数组值是调用者/divisor ,所得的商
第二个数组值是调用者%divisor ,所得的余数

    BigDecimal bigDecimal = new BigDecimal(123.22).setScale(2, BigDecimal.ROUND_HALF_UP);
    System.out.println("bigDecimal 123.22 setScale 2 =" + bigDecimal);
    BigDecimal[] bigDecimals = bigDecimal.divideAndRemainder(new BigDecimal(5));
    System.out.println("bigDecimal 123.22/5 bigDecimals[0] setScale 2 =" + bigDecimals[0]);
    System.out.println("bigDecimal 123.22/5 bigDecimals[1] setScale 2 =" + bigDecimals[1]);
    System.out.println("==================================================================");
    bigDecimal = new BigDecimal(123.22);
    bigDecimals = bigDecimal.divideAndRemainder(new BigDecimal(5));
    System.out.println("bigDecimal 123.22/5 bigDecimals[0] =" + bigDecimals[0]);
    System.out.println("bigDecimal 123.22/5 bigDecimals[1] =" + bigDecimals[1]);
    System.out.println("==================================================================");
    bigDecimal = new BigDecimal(123.22);
    bigDecimals = bigDecimal.divideAndRemainder(new BigDecimal(5),new MathContext(4,RoundingMode.HALF_UP));
    System.out.println("bigDecimal 123.22/5 bigDecimals[0] MathContext 4 =" + bigDecimals[0]);
    System.out.println("bigDecimal 123.22/5 bigDecimals[1] MathContext 4 =" + bigDecimals[1]);

运行结果:

    bigDecimal 123.22 setScale 2 =123.22
    bigDecimal 123.22/5 bigDecimals[0] setScale 2 =24.00
    bigDecimal 123.22/5 bigDecimals[1] setScale 2 =3.22
    ==================================================================
    bigDecimal 123.22/5 bigDecimals[0] =24.000000000000000000000000000000000000000000000
    bigDecimal 123.22/5 bigDecimals[1] =3.219999999999998863131622783839702606201171875
    ==================================================================
    bigDecimal 123.22/5 bigDecimals[0] MathContext 4 =24.00
    bigDecimal 123.22/5 bigDecimals[1] MathContext 4 =3.219999999999998863131622783839702606201171875

9、其他方法

方法介绍格式:返回的数据类型 方法名

1、BigDecimal	abs()
返回BigDecimal其值是this的绝对值BigDecimal,其标度是的 this.scale()。
2、BigDecimal	abs(MathContext mc)
返回BigDecimal其值为this的绝对值的BigDecimal,并根据上下文设置进行舍入。
3、boolean	equals(Object x)
将其BigDecimal与指定 Object的相等性进行比较。
4、BigDecimal	max(BigDecimal val)
返回此BigDecimal和的最大值val。
5、BigDecimal	min(BigDecimal val)
返回此BigDecimal和 的最小值val。
6、BigDecimal	movePointLeft(int n)
返回一个BigDecimal等于此值的小数点n向左移动的a。
7、BigDecimal	movePointRight(int n)
返回一个BigDecimal等于此值的小数点n向右移动的a。
8、BigDecimal	negate()
返回BigDecimal其值为(-this),其标度为的this.scale()。
9、BigDecimal	pow(int n)
返回BigDecimal其值为 (this n),精确地计算出幂,并且精度不受限制。
10、BigDecimal	scaleByPowerOfTen(int n)
返回其数值等于(this* 10 n)的BigDecimal 
11、BigDecimal	stripTrailingZeros()
返回一个BigDecimal从数字上等于该数字的a ,但从表示形式中删除了所有尾随零。
12、String	toEngineeringString()
BigDecimal如果需要指数,则使用工程符号返回this的字符串表示形式。
13、String	toPlainString()
返回BigDecimal 不带指数字段的字符串表示形式。


三、BigDecimal使用要注意

1、如果是new BigDecimal(float/double),或者对没有小数位数限制的对象进行操作,

要进行setScale小数位数控制,否则小数的位数是不确定的。

2、除法的时候出现异常

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result

原因分析:
? 通过BigDecimal的divide方法进行除法时当不整除,出现无限循环小数时,
就会抛异常:java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.

解决方法:
? divide方法设置精确的小数点,如:divide(xxxxx,2)

3、尽量使用参数类型为String的构造函数

如果想详细看其他BigDecimal方法可以上官网看,或者下载api文档查看。
java1.8 api文档下载:https://download.csdn.net/download/wenzhi20102321/9619913

良好的习惯和坚定的行动

你可能感兴趣的:(android,java)