BigDecimal的使用

BigDecimal的使用

1、BigDecimal常用构造函数

  • BigDecimal(int)

创建一个具有参数所指定整数值的对象

  • BigDecimal(double)

创建一个具有参数所指定双精度值的对象

  • BigDecimal(long)

创建一个具有参数所指定长整数值的对象

  • BigDecimal(String)

创建一个具有参数所指定以字符串表示的数值的对象

2、使用的一些坑

java 复制代码
BigDecimal a = new BigDecimal(0.1);
System.out.println("a的值:"+a);
System.out.println("=====================");
BigDecimal b = new BigDecimal("0.1");
System.out.println("b的值:"+b);
sh 复制代码
a的值:0.1000000000000000055511151231257827021181583404541015625
=====================
b的值:0.1

3、BigDecimal常用方法

1、常用方法
  • add(BigDecimal)

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

  • ubtract(BigDecimal)

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

  • multiply(BigDecimal)

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

  • divide(BigDecimal)

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

  • toString()

将BigDecimal对象中的值转换成字符串

  • doubleValue()

将BigDecimal对象中的值转换成双精度数

  • floatValue()

将BigDecimal对象中的值转换成单精度数

  • longValue()

将BigDecimal对象中的值转换成长整数

  • intValue()

将BigDecimal对象中的值转换成整数

2、BigDecimal大小比较

java中对BigDecimal比较大小一般用的是bigdemical的compareTo方法

java 复制代码
int a = bigdemical.compareTo(bigdemical2);

返回结果分析:

java 复制代码
a = -1,表示bigdemical小于bigdemical2;
a = 0,表示bigdemical等于bigdemical2;
a = 1,表示bigdemical大于bigdemical2;

a大于等于b

java 复制代码
new bigdemica(a).compareTo(new bigdemical(b)) >= 0
java 复制代码
BigDecimal a =new BigDecimal("0.10");
BigDecimal b =new BigDecimal("0.1");
System.out.println(a == b);
System.out.println(a.equals(b));
System.out.println(a.compareTo(b));
java 复制代码
false
false
0
3、BigDecimal格式化

由于NumberFormat类的format()方法可以使用BigDecimal对象作为其参数,可以利用BigDecimal对超出16位有效数字的货币值,百分值,以及一般数值进行格式化控制。

以利用BigDecimal对货币和百分比格式化为例。首先,创建BigDecimal对象,进行BigDecimal的算术运算后,分别建立对货币和百分比格式化的引用,最后利用BigDecimal对象作为format()方法的参数,输出其格式化的货币值和百分比。

java 复制代码
NumberFormat currency = NumberFormat.getCurrencyInstance(); //建立货币格式化引用
NumberFormat percent = NumberFormat.getPercentInstance(); //建立百分比格式化引用
percent.setMaximumFractionDigits(3); //百分比小数点最多3位

BigDecimal loanAmount = new BigDecimal("15000.48"); //贷款金额
BigDecimal interestRate = new BigDecimal("0.008"); //利率
BigDecimal interest = loanAmount.multiply(interestRate); //相乘

System.out.println("贷款金额:\t" + currency.format(loanAmount));
System.out.println("利率:\t" + percent.format(interestRate));
System.out.println("利息:\t" + currency.format(interest));
java 复制代码
贷款金额:	¥15,000.48
利率:	0.8%
利息:	¥120.00

BigDecimal格式化保留2为小数,不足则补0:

java 复制代码
package com.xx.bigdecimal;

import java.math.BigDecimal;
import java.text.DecimalFormat;

/**
 * @Author: xueqimiao
 * @Date: 2023/11/20 09:09
 */
public class BigDecimalTest {

    public static void main(String[] args) {
        System.out.println(formatToNumber(new BigDecimal("3.435")));
        System.out.println(formatToNumber(new BigDecimal(0)));
        System.out.println(formatToNumber(new BigDecimal("0.00")));
        System.out.println(formatToNumber(new BigDecimal("0.001")));
        System.out.println(formatToNumber(new BigDecimal("0.006")));
        System.out.println(formatToNumber(new BigDecimal("0.206")));
    }

    public static String formatToNumber(BigDecimal obj) {
        DecimalFormat df = new DecimalFormat("#0.00");
        return df.format(obj).toString();
    }
}
java 复制代码
3.44
0.00
0.00
0.00
0.01
0.21
4、SpringBoot应用参数格式化
java 复制代码
package com.xx.vo;

import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;

/**
 * @Author: xueqimiao
 * @Date: 2023/11/20 09:23
 */
@Data
public class BigDecimalVO implements Serializable {

    private BigDecimal score;

    private BigDecimal scoreTo;
}
java 复制代码
@GetMapping("/testDecimal")
public ResultData test(){
    BigDecimalVO bigDecimalVO = new BigDecimalVO();
    bigDecimalVO.setScore(new BigDecimal("0"));
    bigDecimalVO.setScoreTo(new BigDecimal("0"));
    return new ResultData(bigDecimalVO);

}

@JsonSerialize 是 Java 中 Jackson 库提供的注解之一,用于定制对象在序列化(将对象转换为 JSON 字符串)过程中的行为。Jackson 是一个流行的 JSON 处理库,用于在 Java 对象和 JSON 数据之间进行转换。

当你在一个类或属性上使用 @JsonSerialize 注解时,你可以指定一个自定义的序列化器(serializer)。序列化器负责将对象转换为 JSON 格式,而不依赖于默认的方式。这可以用于处理一些特殊的需求,例如将对象以不同的方式序列化,或者在序列化过程中执行一些特殊的逻辑。

java 复制代码
package com.xx.config;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;
import java.math.BigDecimal;
import java.text.DecimalFormat;

/**
 * @Author: xueqimiao
 * @Date: 2023/11/20 09:29
 */
public class BigDecimalSerializer extends JsonSerializer<BigDecimal> {

    @Override
    public void serialize(BigDecimal value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (value != null) {
            gen.writeString(new DecimalFormat("#0.00").format(value));
        }
    }
}
java 复制代码
@Data
public class BigDecimalVO implements Serializable {

    private BigDecimal score;

    @JsonSerialize(using = BigDecimalSerializer.class)
    private BigDecimal scoreTo;
}
5、BigDecimal常见异常
java 复制代码
public static void main(String[] args) {
    BigDecimal bigDecimal = new BigDecimal(1);
    BigDecimal bigDecimal2 = new BigDecimal(3);
    System.out.println(bigDecimal.divide(bigDecimal2));
}
java 复制代码
Exception in thread "main" java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
	at java.base/java.math.BigDecimal.divide(BigDecimal.java:1780)
	at com.xx.bigdecimal.BigDecimalTest.main(BigDecimalTest.java:15)

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

java 复制代码
public static void main(String[] args) {
    BigDecimal bigDecimal = new BigDecimal(1);
    BigDecimal bigDecimal2 = new BigDecimal(3);
    BigDecimal result = bigDecimal.divide(bigDecimal2, 2, BigDecimal.ROUND_HALF_UP);
    System.out.println(result);
}

2表示2位小数,BigDecimal.ROUND_HALF_UP 是舍入模式,表示使用四舍五入。你可以根据你的需求选择不同的精度和舍入模式

4、BigDecimal工具类

java 复制代码
package com.xx.util;

import com.xx.utils.ValidationUtil;

import java.math.BigDecimal;

/**
 * @Author: xueqimiao
 * @Date: 2023/11/20 10:15
 */
public class BigDecimalUtil {

    /**
     * 累加
     *
     * @param values
     * @return
     */
    public static BigDecimal add(BigDecimal... values) {
        if (ValidationUtil.isEmpty(values) || values.length == 0) {
            return new BigDecimal(0);
        }
        if (values.length == 1) {
            return values[0];
        } else {
            BigDecimal returnNum = ValidationUtil.isEmpty(values[0]) ? new BigDecimal(0) : values[0];
            for (int i = 1; i < values.length; i++) {
                if (ValidationUtil.isEmpty(values[i])) {
                    continue;
                }
                BigDecimal b1 = returnNum;
                BigDecimal b2 = values[i];
                returnNum = b1.add(b2);
            }
            return returnNum;
        }
    }

    /**
     * 减法
     *
     * @param param
     * @return
     */
    public static BigDecimal subtract(BigDecimal... param) {
        if (ValidationUtil.isEmpty(param) || param.length == 0) {
            return new BigDecimal(0);
        }
        BigDecimal sumLess = param[0];//被减数
        for (int i = 1; i < param.length; i++) {
            BigDecimal bigDecimal = param[i] == null ? new BigDecimal(0) : param[i];
            sumLess = sumLess.subtract(bigDecimal);
        }
        return sumLess;
    }

    /**
     * 乘以
     *
     * @param v1
     * @param v2
     * @return
     */
    public static BigDecimal multiply(BigDecimal v1, BigDecimal v2) {
        if (ValidationUtil.isEmpty(v1) || ValidationUtil.isEmpty(v2)) {
            return new BigDecimal(0);
        }
        BigDecimal multiply = v1.multiply(v2);
        return multiply;
    }

    /**
     * 除以
     *
     * @param v1
     * @param v2
     * @return
     */
    public static BigDecimal divide(BigDecimal v1, BigDecimal v2) {
        if (ValidationUtil.isEmpty(v1) || ValidationUtil.isEmpty(v2) || v2.compareTo(new BigDecimal("0")) == 0) {
            return new BigDecimal(0);
        }
        return v1.divide(v2, 3, BigDecimal.ROUND_HALF_DOWN);
    }

    /**
     * 提供精确的减法运算
     *
     * @param v1    被减数
     * @param v2    减数
     * @param scale 保留scale 位小数
     * @return 两个参数的差
     */
    public static String sub(String v1, String v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 提供精确的乘法运算
     *
     * @param v1    被乘数
     * @param v2    乘数
     * @param scale 保留scale 位小数
     * @return 两个参数的积
     */
    public static double mul(double v1, double v2, int scale) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return round(b1.multiply(b2).doubleValue(), scale);
    }

    /**
     * 提供精确的乘法运算
     *
     * @param v1    被乘数
     * @param v2    乘数
     * @param scale 保留scale 位小数
     * @return 两个参数的积
     */
    public static String mul(String v1, String v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
     * 定精度,以后的数字四舍五入
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 表示表示需要精确到小数点以后几位。
     * @return 两个参数的商
     */
    public static double div(double v1, double v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
     * 定精度,以后的数字四舍五入
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 表示需要精确到小数点以后几位
     * @return 两个参数的商
     */
    public static String div(String v1, String v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v1);
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 提供精确的小数位四舍五入处理
     *
     * @param v     需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static double round(double v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(Double.toString(v));
        return b.setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    /**
     * 提供精确的小数位四舍五入处理
     *
     * @param v     需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return 四舍五入后的结果
     */
    public static String round(String v, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b = new BigDecimal(v);
        return b.setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 取余数
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 小数点后保留几位
     * @return 余数
     */
    public static String remainder(String v1, String v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 取余数 BigDecimal
     *
     * @param v1    被除数
     * @param v2    除数
     * @param scale 小数点后保留几位
     * @return 余数
     */
    public static BigDecimal remainder(BigDecimal v1, BigDecimal v2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException(
                    "The scale must be a positive integer or zero");
        }
        return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 比较大小
     *
     * @param v1 被比较数
     * @param v2 比较数
     * @return 如果v1 大于v2 则 返回true 否则false
     */
    public static boolean compare(String v1, String v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        int bj = b1.compareTo(b2);
        boolean res;
        if (bj > 0)
            res = true;
        else
            res = false;
        return res;
    }
}
相关推荐
专注API从业者21 分钟前
Open Claw 京东商品监控选品实战:一键抓取、实时监控、高效选品
java·服务器·数据库
摇滚侠38 分钟前
DBeaver 导入数据库 导入 SQL 文件 MySQL 备份恢复
java·数据库·mysql
keep one's resolveY1 小时前
SpringBoot实现重试机制的四种方案
java·spring boot·后端
天空属于哈夫克32 小时前
企业微信API常见的错误和解决方案
java·数据库·企业微信
摇滚侠2 小时前
VMvare 虚拟机 Oracle19c 安装步骤,远程连接 Oracle19c,百度网盘安装包
java·oracle
梁萌2 小时前
idea报错找不到XX包的解决方法
java·intellij-idea·启动报错·缺少包
Agent产品评测局3 小时前
生产排期与MES/ERP系统打通,实操方法详解 —— 2026企业级智能体自动化选型与实战指南
java·运维·人工智能·ai·chatgpt·自动化
阿丰资源3 小时前
基于Spring Boot的电影城管理系统(直接运行)
java·spring boot·后端
呱牛do it3 小时前
企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 8)
java
消失的旧时光-19434 小时前
Spring Boot 工程化进阶:统一返回 + 全局异常 + AOP 通用工具包
java·spring boot·后端·aop·自定义注解