A classe de API BigDecimal fornecida por Java no pacote java.math é usada para realizar operações precisas em números com mais de 16 dígitos significativos. A variável de ponto flutuante de precisão dupla double pode lidar com 16 dígitos significativos. Em aplicações práticas, é necessário realizar operações e processamento em números maiores ou menores. Float e double só podem ser usados para cálculos científicos ou cálculos de engenharia. Java.math.BigDecimal deve ser usado em cálculos comerciais. O que BigDecimal cria é um objeto. Não podemos usar operadores aritméticos tradicionais como +, -, *, / para realizar operações matemáticas diretamente em seu objeto, mas devemos chamar seu método correspondente. Os parâmetros no método também devem ser objetos de BigDecimal. Construtor é um método especial da classe, especialmente usado para criar objetos, especialmente objetos com parâmetros.
1. Método de construção
Existem 4 métodos de construção para BigDecimal:
BigDecimal (int): Cria um objeto com o valor inteiro especificado pelo parâmetro.
BigDecimal (double): Cria um objeto com o valor de precisão dupla especificado pelo parâmetro (não recomendado).
BigDecimal (long): Cria um objeto com o valor inteiro longo especificado pelo parâmetro.
BigDecimal (String): Crie um objeto com o valor numérico representado pela string especificada pelo parâmetro.
Por que o segundo método de construção não é recomendado? O seguinte código:
/**
* 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);
}
Resultados de:
A causa do problema: De acordo com a descrição no JDK, o resultado do método de construção com um parâmetro do tipo double é um tanto imprevisível.
2. Adição, subtração, multiplicação e divisão
BigDecimal operações de adição, subtração, multiplicação e divisão.
Adição: use o método add ().
Subtração: use o método subtract ().
Multiplicação: use o método multiply ().
Divisão: use o método 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);
}
Resultados de:
Use a biblioteca de classes da ferramenta Hutool para calcular adição, subtração, multiplicação e divisão BigDecimal, mantendo duas casas decimais.
/**
* 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);
}
Resultados de:
3. Arredondamento
(1) Arredondamento de BigDecimal e duas casas decimais.
/**
* 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);
}
Observação: se você estiver no setor de finanças da Internet, tente usar ROUND_HALF_EVEN (método de arredondamento bancário) ao fazer o cálculo.
Resultados de:
(2) Saída de arredondamento e formatação de 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. Compare o tamanho
O tamanho de comparação de BigDecimal pode usar o método compareTo (BigDecimal val), que retorna o resultado da seguinte maneira:
- Retorne quando A for maior que B: 1
- Quando A é igual a B, ele retorna: 0
- Retorne quando A for menor que 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("小于");
}
}
Resultados de:
5. Estatísticas de fundos
Para campos relacionados a fundos, o tipo de dados BigDecimal é geralmente usado.
[Exemplo] Estatísticas de informações salariais do usuário.
/**
* 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 + "元");
}
Resultados de:
6. Tipo de conversão
(1) Converta o tipo BigDecimal em outros tipos de dados.
/**
* 将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);
}
Resultados de:
(2) Converta o objeto no tipo 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);
}