首页 > 编程语言 > java 使用BigDecimal进行货币金额计算的操作
2021
02-21

java 使用BigDecimal进行货币金额计算的操作

float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用 java.math.BigDecimal。

而且使用BigDecimal类也可以进行大数的操作。

方法 类型 描述
public BigDecimal(double val) 构造 将double表示形式转换为BigDecimal
public BigDecimal(int val) 构造 将int表示形式转换为BigDecimal
public BigDecimal(String val) 构造 将字符串表示形式转换为BigDecimal
public BigDecimal add(BigDecimal augend) 普通 加法
public BigDecimal subtract(BigDecimal subtrahend) 普通 减法
public BigDecimal multiply(BigDecimal multiplicand) 普通 乘法
public BigDecimal divide(BigDecimal divisor) 普通 除法

一、 BigDecimal的计算

金额的计算BigDecimal类

double d = 9.84;
double d2 = 1.22;
//注意需要使用BigDecimal(String val)构造方法
BigDecimal bigDecimal = new BigDecimal(Double.toString(d));
BigDecimal bigDecimal2 = new BigDecimal(Double.toString(d2));
//加法
BigDecimal bigDecimalAdd = bigDecimal.add(bigDecimal2);
double add = bigDecimalAdd.doubleValue();
//减法
BigDecimal bigDecimalSubtract = bigDecimal.subtract(bigDecimal2);
double subtract = bigDecimalSubtract.doubleValue();
//乘法
BigDecimal bigDecimalMultiply = bigDecimal.multiply(bigDecimal2);
double multiply = bigDecimalMultiply.doubleValue();
//除法
int scale = 2;//保留2位小数
BigDecimal bigDecimalDivide = bigDecimal.divide(bigDecimal2, scale, BigDecimal.ROUND_HALF_UP);
double divide = bigDecimalDivide.doubleValue();
//格式化
double format = 12343171.6;
//获取常规数值格式
NumberFormat number = NumberFormat.getNumberInstance();
String str = number.format(format);//12,343,171.6
//获取整数数值格式
NumberFormat integer = NumberFormat.getIntegerInstance();
str = integer.format(format);//如果带小数会四舍五入到整数12,343,172
//获取货币数值格式
NumberFormat currency = NumberFormat.getCurrencyInstance();
currency.setMinimumFractionDigits(2);//设置数的小数部分所允许的最小位数(如果不足后面补0)
currency.setMaximumFractionDigits(4);//设置数的小数部分所允许的最大位数(如果超过会四舍五入)
str = currency.format(format);//¥12,343,171.60
//获取显示百分比的格式
NumberFormat percent = NumberFormat.getPercentInstance();
percent.setMinimumFractionDigits(2);//设置数的小数部分所允许的最小位数(如果不足后面补0)
percent.setMaximumFractionDigits(3);//设置数的小数部分所允许的最大位数(如果超过会四舍五入)
str = percent.format(format);//1,234,317,160.00%

二、典型的Double类型的数值运算

/**
 * double的计算不精确,会有类似0.0000000000000002的误差,正确的方法是使用BigDecimal或者用整型
 * 整型地方法适合于货币精度已知的情况,比如12.11+1.10转成1211+110计算,最后再/100即可
 * 以下是摘抄的BigDecimal方法:
 */
public class DoubleUtil implements Serializable {
 private static final long serialVersionUID = -3345205828566485102L;
 // 默认除法运算精度
 private static final Integer DEF_DIV_SCALE = 2;
 /**
  * 提供精确的加法运算。
  *
  * @param value1 被加数
  * @param value2 加数
  * @return 两个参数的和
  */
 public static Double add(Double value1, Double value2) {
  BigDecimal b1 = new BigDecimal(Double.toString(value1));
  BigDecimal b2 = new BigDecimal(Double.toString(value2));
  return b1.add(b2).doubleValue();
 }
 /**
  * 提供精确的减法运算。
  *
  * @param value1 被减数
  * @param value2 减数
  * @return 两个参数的差
  */
 public static double sub(Double value1, Double value2) {
  BigDecimal b1 = new BigDecimal(Double.toString(value1));
  BigDecimal b2 = new BigDecimal(Double.toString(value2));
  return b1.subtract(b2).doubleValue();
 }
 /**
  * 提供精确的乘法运算。
  *
  * @param value1 被乘数
  * @param value2 乘数
  * @return 两个参数的积
  */
 public static Double mul(Double value1, Double value2) {
  BigDecimal b1 = new BigDecimal(Double.toString(value1));
  BigDecimal b2 = new BigDecimal(Double.toString(value2));
  return b1.multiply(b2).doubleValue();
 }
 /**
  * 提供(相对)精确的除法运算,当发生除不尽的情况时, 精确到小数点以后10位,以后的数字四舍五入。
  *
  * @param dividend 被除数
  * @param divisor 除数
  * @return 两个参数的商
  */
 public static Double divide(Double dividend, Double divisor) {
  return divide(dividend, divisor, DEF_DIV_SCALE);
 }
 /**
  * 提供(相对)精确的除法运算。 当发生除不尽的情况时,由scale参数指定精度,以后的数字四舍五入。
  *
  * @param dividend 被除数
  * @param divisor 除数
  * @param scale 表示表示需要精确到小数点以后几位。
  * @return 两个参数的商
  */
 public static Double divide(Double dividend, Double divisor, Integer scale) {
  if (scale < 0) {
   throw new IllegalArgumentException("The scale must be a positive integer or zero");
  }
  BigDecimal b1 = new BigDecimal(Double.toString(dividend));
  BigDecimal b2 = new BigDecimal(Double.toString(divisor));
  return b1.divide(b2, scale,RoundingMode.HALF_UP).doubleValue();
 }
 /**
  * 提供指定数值的(精确)小数位四舍五入处理。
  *
  * @param value 需要四舍五入的数字
  * @param scale 小数点后保留几位
  * @return 四舍五入后的结果
  */
 public static double round(double value,int scale){
  if(scale<0){
   throw new IllegalArgumentException("The scale must be a positive integer or zero");
  }
  BigDecimal b = new BigDecimal(Double.toString(value));
  BigDecimal one = new BigDecimal("1");
  return b.divide(one,scale, RoundingMode.HALF_UP).doubleValue();
 }
}

补充:Java存储金额解决方案BigDecimal

使用BigDecimal来存储金额数据,数据库中使用decimal类型,长度18,小数点2。

在JPA中创建时如下:

@Column(columnDefinition="decimal(18,2)") 
private BigDecimal price; //商品价格

在数据库中创建时如下:

常用构造器:

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

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

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

常用方法:加减乘除

add(BigDecimal) BigDecimal对象中的值相加,返回BigDecimal对象

subtract(BigDecimal) BigDecimal对象中的值相减,返回BigDecimal对象

multiply(BigDecimal) BigDecimal对象中的值相乘,返回BigDecimal对象

divide(BigDecimal) BigDecimal对象中的值相除,返回BigDecimal对象

常用方法:数据转换

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

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

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

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

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

以上为个人经验,希望能给大家一个参考,也希望大家多多支持自学编程网。如有错误或未考虑完全的地方,望不吝赐教。

编程技巧