当前位置: 首页 > 编程笔记 >

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

鲁鹏
2023-03-14
本文向大家介绍java 使用BigDecimal进行货币金额计算的操作,包括了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对象中的值转换成整数

以上为个人经验,希望能给大家一个参考,也希望大家多多支持小牛知识库。如有错误或未考虑完全的地方,望不吝赐教。

 类似资料:
  • 给定一美元金额,将其转换为欧元硬币和纸币。你得到了美元金额作为论据,并说美元对欧元的汇率是1.30。你可以看到欧元的名称是500美元,200美元,100美元,50美元,20美元,10美元,5美元,2美元,1美元,50美分,25美分,10美分,5美分,2美分,1美分。将该美元金额转换为最小金额的纸币和硬币。(将数字美元金额(如10.00美元)转换为等值的欧元纸币和硬币。) 免责声明:这是我收到的家庭

  • 我正在尝试实现以下CFC(coldfusion)代码: http://www.sitekickr.com/blog/integrating-paypal-payflow-pro-rest-api/ 我仍处于测试阶段,甚至没有尝试传递自己的变量,只是使用提供的CFSET示例。 我得到了这个错误: {“name”:“VALIDATION_ERROR”,“details”:[{“field”:“tran

  • 我得到了这个错误: {“name”:“validation_error”,“details”:[{“field”:“transactions[0].amount.total”,“issue”:“币种金额必须为非负数,可以选择精确包含小数点后2位,以”.“分隔,可选千位分隔符”,“,小数点前限7位”}],“message”:“请求无效-请参阅详细信息”,“information_link”:“htt

  • 我有一个用户输入框,用户可以在其中键入美元货币的金额。当用户输入小数点以表示0.24美分(例如0.24美分)时,当输入为.244或.240时,该值显示为0.20而不是.24美分。我希望用户能够只输入0.24美分,而不必输入额外的小数。

  • 我们正在开发旅游网站,用于预订航班、酒店、汽车等。它是基于产品的软件。客户(购买我们的软件)将成为“主要代理”。他的交易总额将是INR(印度卢比货币)。所有航班、酒店或汽车预订仅以INR进行。 现在他有权创建他的“子机构”。子机构货币可以是美元或印度卢比等。这意味着“主要机构”可能在世界各地都有其子机构。现在,每当“子机构”登录时,他的交易报告都应该使用他的货币。如果其货币为“澳元”,则交易总额应