BigDecimal
简介
为了避免浮点数(float
与double
)在运算时出现的精度丢失问题,也为了应对超出16位有效数字的运算场景,因此,在实际应用中,我们经常用到BigDecimal来代替浮点数进行运算。
BigDecimal所创建的是对象,因此我们不能够使用传统的加减乘除符号直接进行数学运算,而是使用相应的函数方法。
在实现四则运算的基础上,BigDecimal还延伸出了不少好用的函数,可以方便、快捷的进行更多运算处理。
基本知识
导包
BigDecimal对象在使用时需要导入包java.math.BigDecimal
import java.math.BigDecimal;
构造方法
BigDecimal有四种构造方法:
- BigDecimal(String)
- BigDecimal(int)
- BigDecimal(long)
- BigDecimal(double)
其中,出于精度问题,不建议使用最后一种double
的构造方法,数据源为double
类型时,请使用Double.toString(double)
将数据先转成字符串,再使用第一种String
构造方法
四则运算
加法 add(BigDecimal)
BigDecimal a = new BigDecimal("2");
BigDecimal b = new BigDecimal("1");
System.out.println("a + b = " + a.add(b));
// 输出结果 a + b = 3
减法 subtract(BigDecimal)
BigDecimal a = new BigDecimal("2");
BigDecimal b = new BigDecimal("1");
System.out.println("a - b = " + a.subtract(b));
// 输出结果 a - b = 1
乘法 multiply(BigDecimal)
BigDecimal a = new BigDecimal("2");
BigDecimal b = new BigDecimal("1");
System.out.println("a * b = " + a.multiply(b));
// 输出结果 a * b = 2
除法 divide(BigDecimal)
BigDecimal a = new BigDecimal("2");
BigDecimal b = new BigDecimal("1");
System.out.println("a / b = " + a.divide(b));
// 输出结果 a / b = 2
除法 divide(BigDecimal, int, int)
在除法运算时,有一个需要注意的地方
在出现不可整除的情况时(如2/1.3
),divide方法会报错
java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
这种情况下,你需要给divide方法传入多个参数
divide(BigDecimal divisor, int scale, int roundingMode)
第一个参数为除数,与单参数时填入的对象一致
第二个参数为小数点后保留的位数
第三个参数为舍入的方式,舍入方式列表如下(示例取一位小数)
- ROUND_UP
- 向远离零的方向舍入
- 例:
- 1.55 -> 1.6
- -1.32 -> -1.4
- ROUND_DOWN
- 向接近零的方向舍入
- 1.55 -> 1.5
- -1.32 -> -1.3
- 向接近零的方向舍入
- ROUND_CEILING
- 向正无穷方向舍入
- 1.55 -> 1.6
- -1.32 -> -1.3
- 向正无穷方向舍入
- ROUND_FLOOR
- 向负无穷方向舍入
- 1.55 -> 1.5
- -1.32 -> -1.4
- 向负无穷方向舍入
- ROUND_HALF_UP
- 四舍五入
- 1.55 -> 1.6
- -1.32 -> -1.3
- 四舍五入
- ROUND_HALF_DOWN
- 五舍六入
- 1.55 -> 1.5
- -1.36 -> -1.4
- 五舍六入
- ROUND_HALF_EVEN
- 四舍六入,五奇入偶舍(上一位为奇数进位,为偶数时舍位)
- 1.55 -> 1.6
- 1.65 -> 1.6
- -1.45 -> -1.4
- -1.55 -> -1.6
- 四舍六入,五奇入偶舍(上一位为奇数进位,为偶数时舍位)
- ROUND_UNNECESSARY
- 不舍入
其他常用方法
绝对值 abs()
使目标取绝对值后返回
比较大小 compareTo(BigDecimal)
场景:A.compareTo(B)
- 当 A>B 时,返回1
- 当 A<B 时,返回-1
- 当 A=B 时,返回0
取大值 max(BigDecimal)
场景:A.compareTo(B)
- 当 A>B 时,返回A
- 当 A<B 时,返回B
- 当 A=B 时,返回A
取小值 min(BigDecimal)
场景:A.compareTo(B)
- 当 A>B 时,返回B
- 当 A<B 时,返回A
- 当 A=B 时,返回A
求幂 pow(int)
使目标计算指定次数的乘方后返回
求余 remainder(BigDecimal)
使目标对参数取余后返回
左移小数点 movePointLeft(int)
使小数点左移指定位数后返回
右移小数点 movePointRight(int)
使小数点右移指定位数后返回
舍入 setScale(int,int)
使目标以对应位数、对应方式进行舍入后返回
自身 plus()
返回目标自身
相反值 negate()
返回目标的相反值
精度 precision()
返回目标的精度/十进制位数(包括小数点前后的位数,不包含小数点与正负号)
符号 signum()
返回目标的符号(1、-1、0)
附:测试文件
Main.java
import java.math.BigDecimal;
public class Main {
public static void main(String[] args) {
{
System.out.println("四则运算:");
BigDecimal a = new BigDecimal("7.2");
BigDecimal b = new BigDecimal("2.4");
System.out.println("a: " + a);
System.out.println("b: " + b);
System.out.println("a.add(b) a + b = " + a.add(b));
System.out.println("a.subtract(b) a - b = " + a.subtract(b));
System.out.println("a.multiply(b) a * b = " + a.multiply(b));
System.out.println("a.divide(b) a / b = " + a.divide(b));
}
{
System.out.println("非整数倍除法:");
BigDecimal a = new BigDecimal("7.2");
BigDecimal b = new BigDecimal("2.3");
System.out.println("a: " + a);
System.out.println("b: " + b);
System.out.println("a / b = " + a.divide(b, 4, BigDecimal.ROUND_HALF_UP));
try {
System.out.println("a / b = " + a.divide(b));
} catch (Exception e) {
// e.printStackTrace();
System.out.println("无法整除时不填入舍位信息将会报错:" + e.getMessage());
}
}
{
System.out.println("绝对值:");
BigDecimal a = new BigDecimal("7.2");
BigDecimal b = new BigDecimal("-2.4");
System.out.println("a: " + a);
System.out.println("b: " + b);
System.out.println("a.abs() " + a + " -> " + a.abs());
System.out.println("b.abs() " + b + " -> " + b.abs());
}
{
System.out.println("比较大小:");
BigDecimal a = new BigDecimal("7.2");
BigDecimal b = new BigDecimal("2.4");
System.out.println("a: " + a);
System.out.println("b: " + b);
System.out.println("a.compareTo(b) a>b -> " + a.compareTo(b));
System.out.println("a.compareTo(b) a<b -> " + b.compareTo(a));
System.out.println("a.compareTo(a) a=b -> " + a.compareTo(a));
}
{
System.out.println("取大取小:");
BigDecimal a = new BigDecimal("7.2");
BigDecimal b = new BigDecimal("2.4");
System.out.println("a: " + a);
System.out.println("b: " + b);
System.out.println("a.max(b) -> " + a.max(b));
System.out.println("a.min(b) -> " + a.min(b));
}
{
System.out.println("取幂:");
BigDecimal a = new BigDecimal("7");
System.out.println("a: " + a);
System.out.println("a.pow(3) -> " + a.pow(3));
}
{
System.out.println("取余:");
BigDecimal a = new BigDecimal("7");
BigDecimal b = new BigDecimal("3");
System.out.println("a: " + a);
System.out.println("b: " + b);
System.out.println("a.remainder(b) -> " + a.remainder(b));
}
{
System.out.println("小数点左右移:");
BigDecimal a = new BigDecimal("123.456");
System.out.println("a: " + a);
System.out.println("a.movePointLeft(1) -> " + a.movePointLeft(1));
System.out.println("a.movePointRight(2) -> " + a.movePointRight(2));
}
{
System.out.println("舍入:");
BigDecimal a = new BigDecimal("123.456");
System.out.println("a: " + a);
System.out.println("ROUND_UP:" + a.setScale(2, BigDecimal.ROUND_UP));
System.out.println("ROUND_DOWN:" + a.setScale(2, BigDecimal.ROUND_DOWN));
System.out.println("ROUND_CEILING:" + a.setScale(2, BigDecimal.ROUND_CEILING));
System.out.println("ROUND_FLOOR:" + a.setScale(2, BigDecimal.ROUND_FLOOR));
System.out.println("ROUND_HALF_UP:" + a.setScale(2, BigDecimal.ROUND_HALF_UP));
System.out.println("ROUND_HALF_DOWN:" + a.setScale(2, BigDecimal.ROUND_HALF_DOWN));
System.out.println("ROUND_HALF_EVEN:" + a.setScale(2, BigDecimal.ROUND_HALF_EVEN));
try {
System.out.println("ROUND_UNNECESSARY:" + a.setScale(2, BigDecimal.ROUND_UNNECESSARY));
} catch (Exception e) {
// e.printStackTrace();
System.out.println("小数位数超过写入的参数时选择不舍入模式会报错:" + e.getMessage());
}
}
{
System.out.println("自身与相反数:");
BigDecimal a = new BigDecimal("123.456");
System.out.println("a: " + a);
System.out.println("a.plus() -> " + a.plus());
System.out.println("a.negate() -> " + a.negate());
}
{
System.out.println("精度与符号:");
BigDecimal a = new BigDecimal("-123.456");
System.out.println("a: " + a);
System.out.println("a.precision() -> " + a.precision());
System.out.println("a.signum() -> " + a.signum());
}
}
}
output
四则运算:
a: 7.2
b: 2.4
a.add(b) a + b = 9.6
a.subtract(b) a - b = 4.8
a.multiply(b) a * b = 17.28
a.divide(b) a / b = 3
非整数倍除法:
a: 7.2
b: 2.3
a / b = 3.1304
无法整除时不填入舍位信息将会报错:Non-terminating decimal expansion; no exact representable decimal result.
绝对值:
a: 7.2
b: -2.4
a.abs() 7.2 -> 7.2
b.abs() -2.4 -> 2.4
比较大小:
a: 7.2
b: 2.4
a.compareTo(b) a>b -> 1
a.compareTo(b) a<b -> -1
a.compareTo(a) a=b -> 0
取大取小:
a: 7.2
b: 2.4
a.max(b) -> 7.2
a.min(b) -> 2.4
取幂:
a: 7
a.pow(3) -> 343
取余:
a: 7
b: 3
a.remainder(b) -> 1
小数点左右移:
a: 123.456
a.movePointLeft(1) -> 12.3456
a.movePointRight(2) -> 12345.6
舍入:
a: 123.456
ROUND_UP:123.46
ROUND_DOWN:123.45
ROUND_CEILING:123.46
ROUND_FLOOR:123.45
ROUND_HALF_UP:123.46
ROUND_HALF_DOWN:123.46
ROUND_HALF_EVEN:123.46
小数位数超过写入的参数时选择不舍入模式会报错:Rounding necessary
自身与相反数:
a: 123.456
a.plus() -> 123.456
a.negate() -> -123.456
精度与符号:
a: -123.456
a.precision() -> 6
a.signum() -> -1
注
文章中未包含所有方法,仅列出常用内容
由于个人水平有限,若文章中出现错误请及时指出