一、初始化问题:尽量用字符串的形式初始化,因为小数在计算机内部根本没法精确表示。
BigDecimal value = new BigDecimal("0.1");
public static void main(String[] args) {
BigDecimal intNum = new BigDecimal(0.1);
System.out.println("int 类型【失精】" + intNum.toPlainString());
BigDecimal stringNum = new BigDecimal("0.1");
System.out.println("string类型【正确】" + stringNum.toPlainString());
}
执行结果:
int 类型【失精】0.1000000000000000055511151231257827021181583404541015625
string类型【正确】0.1
二、加减乘除 + 绝对值
public BigDecimal add(BigDecimal value); //加法
public BigDecimal subtract(BigDecimal value); //减法
public BigDecimal multiply(BigDecimal value); //乘法
public BigDecimal divide(BigDecimal value); //除法
public BigDecimal abs(BigDecimal value); //绝对值
比较大小:使用compareTo()方法来比较,它根据两个值的大小分别返回 正数、负数 和 0 ,分别表示大于、小于和等于
if (a.compareTo(b)>0) # a > b
if (a.compareTo(b)<0) # a < b
if (a.compareTo(b)==0) # a = b
if (a.compareTo(b)>=0) # a >= b
if (a.compareTo(b)<=0) # a <= b
注意:不要使用equals(),在比较两个BigDecimal的值是否相等时,要特别注意,使用equals()方法不但要求两个BigDecimal的值相等,还要求它们的scale()相等:
BigDecimal d1 = new BigDecimal("123.456");
BigDecimal d2 = new BigDecimal("123.45600");
System.out.println(d1.equals(d2)); // false,因为scale不同
System.out.println(d1.equals(d2.stripTrailingZeros())); // true,因为d2去除尾部0后scale变为2
System.out.println(d1.compareTo(d2)); // 0
小数位问题:BigDecimal.setScale($保留位数,$舍入方式);
//直接删除多余的小数位,如4.32579保留4位为4.3257(小数点后没有四位则自动补0)
new BigDecimal(4.32579).setScale(4, BigDecimal.ROUND_DOWN);
//进位处理,如4.32579保留4位为4.3258
new BigDecimal(4.32579).setScale(4, BigDecimal.ROUND_UP);
//四舍五入,如4.32579保留4位为4.3258
new BigDecimal(4.32575).setScale(4, BigDecimal.ROUND_HALF_UP);
//四舍五入,如4.32579保留4位为4.3258,如果是5则向上进位
new BigDecimal(4.32575).setScale(4, BigDecimal.ROUND_HALF_DOWN);
三、DEMO
BigDecimal bg = new BigDecimal(“111231.5585”);
//保留2位小数,逢5向上进位
String f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString();
//保留2位小数,逢5向下进位
//BigDecimal setScale = bg.setScale(2,BigDecimal.ROUND_HALF_DOWN);
System.out.println(f1);
八种舍入模式
1、BigDecimal.ROUND_UP
舍入远离零的舍入模式。
在丢弃非零部分之前始终增加数字(始终对非零舍弃部分前面的数字加1)。
注意,此舍入模式始终不会减少计算值的大小。
2、BigDecimal.ROUND_DOWN
接近零的舍入模式。
在丢弃某部分之前始终不增加数字(从不对舍弃部分前面的数字加1,即截短)。
注意,此舍入模式始终不会增加计算值的大小。
3、BigDecimal.ROUND_CEILING
接近正无穷大的舍入模式。
如果 BigDecimal 为正,则舍入行为与 ROUND_UP 相同;
如果为负,则舍入行为与 ROUND_DOWN 相同。
注意,此舍入模式始终不会减少计算值。
4、BigDecimal.ROUND_FLOOR
接近负无穷大的舍入模式。
如果 BigDecimal 为正,则舍入行为与 ROUND_DOWN 相同;
如果为负,则舍入行为与 ROUND_UP 相同。
注意,此舍入模式始终不会增加计算值。
5、BigDecimal.ROUND_HALF_UP
向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为向上舍入的舍入模式。
如果舍弃部分 >= 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同。
注意,这是我们大多数人在小学时就学过的舍入模式(四舍五入)。
6、BigDecimal.ROUND_HALF_DOWN
向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则为上舍入的舍入模式。
如果舍弃部分 > 0.5,则舍入行为与 ROUND_UP 相同;否则舍入行为与 ROUND_DOWN 相同(五舍六入)。
7、BigDecimal.ROUND_HALF_EVEN
向“最接近的”数字舍入,如果与两个相邻数字的距离相等,则向相邻的偶数舍入。
如果舍弃部分左边的数字为奇数,则舍入行为与 ROUND_HALF_UP 相同;
如果为偶数,则舍入行为与 ROUND_HALF_DOWN 相同。
注意,在重复进行一系列计算时,此舍入模式可以将累加错误减到最小。
此舍入模式也称为“银行家舍入法”,主要在美国使用。四舍六入,五分两种情况。
如果前一位为奇数,则入位,否则舍去。
以下例子为保留小数点1位,那么这种舍入方式下的结果。
1.15>1.2 1.25>1.2
8、BigDecimal.ROUND_UNNECESSARY
断言请求的操作具有精确的结果,因此不需要舍入。
如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。
BigDecimal的3个 toString() 方法
BigDecimal类有3个toString方法,分别是toEngineeringString、toPlainString和toString
toEngineeringString:有必要时使用工程计数法。工程记数法是一种工程计算中经常使用的记录数字的方法,与科学技术法类似,但要求10的幂必须是3的倍数
toPlainString:不使用任何指数
toString:有必要时使用科学计数法
不使用指数 | 科学记数法 | 工程记数法 |
---|---|---|
2700 | 2.7 × 10³ | 2.7 × 10³ |
27000 | 2.7 × 10⁴ | 27 × 10³ |
270000 | 2.7 × 10⁵ | 270 × 10³ |
2700000 | 2.7 × 10⁶ | 2.7 × 10⁶ |
public static void main(String[] args) {
BigDecimal bg = new BigDecimal("1E11");
System.out.println(bg.toEngineeringString());
System.out.println(bg.toPlainString());
System.out.println(bg.toString());
}
执行结果:
100E+9
100000000000
1E+11