一、初始化问题:尽量用字符串的形式初始化,因为小数在计算机内部根本没法精确表示。

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() 方法

  1. 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

不为明天而烦恼,不为昨天而叹息,只为今天更美好