Java中BigDecimal的使用:加减乘除、四舍五入、比较大小、资金统计

Java在 java.math 包中提供的API类 BigDecimal,用来对超过16位有效位的数进行精确的运算。双精度浮点型变量double可以处理16位有效数。在实际应用中,需要对更大或者更小的数进行运算和处理。float和double只能用来做科学计算或者是工程计算,在商业计算中要用 java.math.BigDecimal。BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。构造器是类的特殊方法,专门用来创建对象,特别是带有参数的对象。

1、构造方法

BigDecimal 一共有4个构造方法:

BigDecimal(int): 创建一个具有参数所指定整数值的对象。

BigDecimal(double) :创建一个具有参数所指定双精度值的对象(不建议)。

BigDecimal(long): 创建一个具有参数所指定长整数值的对象。

BigDecimal(String) :创建一个具有参数所指定以字符串表示的数值的对象 。

为什么不建议采用第二种构造方法?如下代码:

/**
 * BigDecimal的构造方法
 * @author pan_junbiao
 */
@Test
public void createBigDecimal()
{
    BigDecimal bigDecimal1 = new BigDecimal(12); //推荐
    BigDecimal bigDecimal2 = new BigDecimal("12.83"); //推荐
    BigDecimal bigDecimal3 = new BigDecimal(12.83); //不推荐

    System.out.println("bigDecimal1的值:" + bigDecimal1);
    System.out.println("bigDecimal2的值:" + bigDecimal2);
    System.out.println("bigDecimal3的值:" + bigDecimal3);
}

执行结果:

问题原因:JDK中的描述,参数类型为double的构造方法的结果有一定的不可预知性。

2、加减乘除

BigDecimal的加减乘除运算。

加法:使用 add() 方法。

减法:使用 subtract() 方法。

乘法:使用 multiply() 方法。

除法:使用 divide() 方法。

/**
 * BigDecimal的加减乘除运算
 * @author pan_junbiao
 */
@Test
public void operationTest()
{
    BigDecimal bigDecimal1 = new BigDecimal("10");
    BigDecimal bigDecimal2 = new BigDecimal("2");

    //加法
    BigDecimal addResult = bigDecimal1.add(bigDecimal2);
    System.out.println("加法运算结果:" + addResult);

    //减法
    BigDecimal subResult = bigDecimal1.subtract(bigDecimal2);
    System.out.println("减法运算结果:" + subResult);

    //乘法
    BigDecimal mulResult = bigDecimal1.multiply(bigDecimal2);
    System.out.println("乘法运算结果:" + mulResult);

    //除法
    BigDecimal divResult = bigDecimal1.divide(bigDecimal2);
    System.out.println("除法运算结果:" + divResult);
}

执行结果:

使用Hutool工具类库运算BigDecimal的加减乘除、保留两位小数。

/**
 * BigDecimal的加减乘除运算
 * @author pan_junbiao
 */
@Test
public void operationTest()
{
    BigDecimal bigDecimal1 = new BigDecimal("10.2567");
    BigDecimal bigDecimal2 = new BigDecimal("2.236");

    //加法
    BigDecimal addResult = NumberUtil.add(bigDecimal1,bigDecimal2);
    System.out.println("加法运算结果:" + addResult);

    //减法
    BigDecimal subResult = NumberUtil.sub(bigDecimal1,bigDecimal2);
    System.out.println("减法运算结果:" + subResult);

    //乘法
    BigDecimal mulResult = NumberUtil.mul(bigDecimal1,bigDecimal2);
    System.out.println("乘法运算结果:" + mulResult);

    //除法
    BigDecimal divResult = NumberUtil.div(bigDecimal1,bigDecimal2);
    System.out.println("除法运算结果:" + divResult);

    //保留两位小数
    BigDecimal roundResult = NumberUtil.round(bigDecimal1,2);
    System.out.println("保留两位小数:" + roundResult);
}

执行结果:

3、四舍五入

(1)BigDecimal的四舍五入,并保留两位小数。

/**
 * BigDecimal的四舍五入,并保留两位小数
 * @author pan_junbiao
 */
@Test
public void roundTest()
{
    BigDecimal bigDecimal1 = new BigDecimal("12.233");
    BigDecimal bigDecimal2 = new BigDecimal("12.288");

    //四舍五入,并保留两位小数
    BigDecimal round1 = bigDecimal1.setScale(2, BigDecimal.ROUND_HALF_UP);
    BigDecimal round2 = bigDecimal2.setScale(2, BigDecimal.ROUND_HALF_UP);

    System.out.println("数值1:" + bigDecimal1);
    System.out.println("四舍五入:" + round1);
    System.out.println("-----------------");
    System.out.println("数值2:" + bigDecimal2);
    System.out.println("四舍五入:" + round2);
}

注意:如果是互联网金融行业,所有在进行计算的时候尽量使用 ROUND_HALF_EVEN(银行家舍入法)。

执行结果:

(2)BigDecimal的四舍五入与格式化输出。

/**
 * BigDecimal的四舍五入与格式化输出
 * @author pan_junbiao
 */
@Test
public void formatTest()
{
    // 保留两位小数,个位无数字填充0
    NumberFormat nformat = NumberFormat.getNumberInstance();
    nformat.setMaximumFractionDigits(2);
    System.out.println(nformat.format(0.2));// 0.2
    System.out.println(nformat.format(0.235));// 0.23
    System.out.println(nformat.format(0.2351));// 0.24
    System.out.println(nformat.format(42));// 42

    // DecimalFormat,是NumberFormat的具体实现子类
    // 保留两位小数,对应位上无数字填充0
    DecimalFormat df = new DecimalFormat("#0.00");
    System.out.println(df.format(0.2));// 0.20
    System.out.println(df.format(0.235));// 0.23
    System.out.println(df.format(0.2351));// 0.2, 因为0.2351在0.23-0.24之间,距离0.24更近,所以输出0.24
    System.out.println(df.format(42));// 42.00

    DecimalFormat df4 = new DecimalFormat();
    // #:位置上无数字不显示
    df4.applyPattern("#.##");
    System.out.println(df4.format(345235.0));// 345235
    // 0:位置上无数字显示0
    df4.applyPattern("0.00");
    System.out.println(df4.format(345235.0));// 345235.00
    // 加负数显示
    df4.applyPattern("-0.00");
    System.out.println(df4.format(345235.34567));// -345235.35
    // 逗号分隔
    df4.applyPattern("-0,000.00");
    System.out.println(df4.format(345235.34567));// -345,235.35
    // 百分位
    df4.applyPattern("0.00%");
    System.out.println(df4.format(0.34567));// 34.57%
    // 千分位
    df4.applyPattern("0.00\u2030");
    System.out.println(df4.format(0.34567));// 345.67‰
    // 科学计数法,E之前是底数的格式,E之后的是指数的格式
    df4.applyPattern("0.00E00");
    System.out.println(df4.format(2342.444));// 2.34E03
    // 格式后面加单位符号
    df4.applyPattern("0.00 KG");
    System.out.println(df4.format(2342.444));// 2342.44 KG
    df4.applyPattern("0.00 QA");
    System.out.println(df4.format(2342.444));// 2342.44 QA

    System.out.println(df4.format(2342.435));// 2342.43 QA
    System.out.println(df4.format(2342.445));// 2342.45 QA

    // String.format
    // 保留两位小数,个位数及小数点后两位无数字填充0,四舍五入
    System.out.println(String.format("%.2f", 0.2));// 0.20
    System.out.println(String.format("%.2f", 0.235));// 0.24
    System.out.println(String.format("%.2f", 0.236));// 0.24
    System.out.println(String.format("%.2f", 42.0));// 42.00
}

4、比较大小

BigDecimal的比较大小可以使用 compareTo(BigDecimal val) 方法,该方法返回结果如下:

  • A大于B时返回:1
  • A等于B时返回:0
  • A小于B时返回:-1
/**
 * BigDecimal的比较大小
 * @author pan_junbiao
 */
@Test
public void compareTest()
{
    BigDecimal bigDecimal1 = new BigDecimal("12.01");
    BigDecimal bigDecimal2 = new BigDecimal("12.88");
    int result = bigDecimal1.compareTo(bigDecimal2);

    System.out.println("数值1:" + bigDecimal1);
    System.out.println("数值2:" + bigDecimal2);
    System.out.println("数值1与数值2的比较值:" + result);
    System.out.print("数值1与数值2的比较结果:");
    if (result == 1)
    {
        System.out.print("大于");
    }
    else if (result == 0)
    {
        System.out.print("等于");
    }
    else if (result == -1)
    {
        System.out.print("小于");
    }
}

执行结果:

5、资金统计

对于资金相关的字段,通常会使用BigDecimal数据类型。

【示例】统计用户薪资信息。

/**
 * BigDecimal类型的统计
 * @author pan_junbiao
 */
@Test
public void BigDecimalTest()
{
    //获取用户列表
    List<User> userList = UserService.getUserList();
 
    //最高薪资
    BigDecimal maxSalary = userList.stream().map(User::getSalary).max((x1, x2) -> x1.compareTo(x2)).get();
 
    //最低薪资
    BigDecimal minSalary = userList.stream().map(User::getSalary).min((x1, x2) -> x1.compareTo(x2)).get();
 
    //薪资总和
    BigDecimal sumSalary = userList.stream().map(User::getSalary).reduce(BigDecimal.ZERO, BigDecimal::add);
 
    //平均薪资
    BigDecimal avgSalary = userList.stream().map(User::getSalary).reduce(BigDecimal.ZERO, BigDecimal::add).divide(BigDecimal.valueOf(userList.size()), 2, BigDecimal.ROUND_HALF_UP);
 
    //打印统计结果
    System.out.println("最高薪资:" + maxSalary + "元");
    System.out.println("最低薪资:" + minSalary + "元");
    System.out.println("薪资总和:" + sumSalary + "元");
    System.out.println("平均薪资:" + avgSalary + "元");
}

执行结果:

6、类型转换

(1)将BigDecimal类型转换成其他数据类型。

/**
 * 将BigDecimal类型转换成其他数据类型
 * @author pan_junbiao
 */
@Test
public void convertTest()
{
    BigDecimal bigDecimal = new BigDecimal("12.88");

    //字符串
    String toString = bigDecimal.toString();
    System.out.println("字符串:" + toString);

    //double值
    double toDouble  =bigDecimal.doubleValue();
    System.out.println("double值:" + toDouble);

    //float值
    float toFloat = bigDecimal.floatValue();
    System.out.println("float值:" + toFloat);

    //long值
    long toLong = bigDecimal.longValue();
    System.out.println("long值:" + toLong);

    //int值
    int toInt = bigDecimal.intValue();
    System.out.println("int值:" + toInt);
}

执行结果:

(2)将Object对象转换成BigDecimal类型。

/**
 * 将Object对象转换成BigDecimal类型
 */
public static BigDecimal toBigDecimal(Object obj)
{
    BigDecimal result = new BigDecimal(0);
    if (obj != null)
    {
        if (obj instanceof BigDecimal)
        {
            result = (BigDecimal) obj;
        }
        else if (obj instanceof String)
        {
            result = new BigDecimal((String) obj);
        }
        else if (obj instanceof BigInteger)
        {
            result = new BigDecimal((BigInteger) obj);
        }
        else if (obj instanceof Number)
        {
            result = new BigDecimal(((Number) obj).doubleValue());
        }
        else
        {
            throw new ClassCastException("Not possible to coerce [" + obj + "] from class " + obj.getClass() + " into a BigDecimal.");
        }
    }
    return result.setScale(2, BigDecimal.ROUND_HALF_UP);
}

猜你喜欢

转载自blog.csdn.net/pan_junbiao/article/details/111406241
今日推荐