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对象中的值转换成整数

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

(0)

相关推荐

  • Java之BigDecimal实现详解

    一.BigDecimal概述 Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理.一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度.所以开发中,如果我们需要精确计算的结果,则必须使用Bi

  • Java用BigDecimal类解决Double类型精度丢失的问题

    本篇要点 简单描述浮点数十进制转二进制精度丢失的原因. 介绍几种创建BigDecimal方式的区别. 整理了高精度计算的工具类. 学习了阿里巴巴Java开发手册关于BigDecimal比较相等的规定. 经典问题:浮点数精度丢失 精度丢失的问题是在其他计算机语言中也都会出现,float和double类型的数据在执行二进制浮点运算的时候,并没有提供完全精确的结果.产生误差不在于数的大小,而是因为数的精度. 关于浮点数存储精度丢失的问题,话题过于庞大,感兴趣的同学可以自行搜索一下:[解惑]剖析floa

  • Java中BigDecimal类的add()的使用详解

    Java中的BigDecimal类的使用: 使用Java中的BigDecimal可以进行精确的计算,但是在使用BigDecimal时我们需要注意它的add()方法,使用它自身的add( )方法并不会改变它原始的值,因为初始化BigDecimal是创建一个了个对象,使用add()方法时也等于是创建了一个对象,若要保存这个对象需要再创建一个对象. 句法: public BigDecimal add(BigDecimal val); public BigDecimal add(BigDecimal v

  • Java踩坑记录之BigDecimal类

    前言 在java.math包中提供了对大数字的操作类,用于进行高精确计算,如BigInteger,BigDecimal类.而平常我们开发中使用最多的float和double只能适用于一般的科学和工程计算,如果要在比较精确的计算方面如货币,那么使用float和double会相应的丢失精度,因此用于精密计算大数字的类BigDecimal就必不可少了.所以BigDecimal适合商业计算场景,用来对超过16位有效位的数进行精确的运算.但是BigDecimal的使用并不像float和double那样,使

  • java中BigDecimal和0比较的示例代码

    BigDecimal 和 0 比较大小 调用BigDecimal中的compareTo方法, 如: int i = bigDecimal.compareTo(BigDecimal.Zero); i=0:表示bigDecimal的值  等于 0 i=1:表示bigDecimal的值与 大于0 i=-1:表示bigDecimal的值与 小于 0 参考案例 BigDecimal num= new BigDecimal("18"); int i=num.compareTo(BigDecimal

  • Java double转BigDecimal的注意事项说明

    先上结论: 不要直接用double变量作为构造BigDecimal的参数. 线上有这么一段Java代码逻辑: 1,接口传来一个JSON串,里面有个数字:57.3. 2,解析JSON并把这个数字保存在一个float变量. 3,把这个float变量赋值给一个 BigDecimal对象,用的是BigDecimal的double参数的构造: new BigDecimal(double val) 4,把这个BigDecimal保存到MySQL数据库,字段类型是decimal(15,2). 这段代码逻辑在线

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

    float和double只能用来做科学计算或者是工程计算,在商业计算中我们要用 java.math.BigDecimal. 而且使用BigDecimal类也可以进行大数的操作. 方法 类型 描述 public BigDecimal(double val) 构造 将double表示形式转换为BigDecimal public BigDecimal(int val) 构造 将int表示形式转换为BigDecimal public BigDecimal(String val) 构造 将字符串表示形式转

  • Java实现的贷款金额计算功能示例

    本文实例讲述了Java实现的贷款金额计算功能.分享给大家供大家参考,具体如下: 问题及代码: /* *Copyright (c)2015,西南大学计信院 *All rights reserved. *文件名称:Helloworld.java *作 者:高硕 *完成日期:2015年10月15日 *版 本 号:v1.0 *问题描述:通过年利率等来计算月支付额和支付总额. *程序输入:年利率.时间.金额. *程序输出:月支付额和总支付额. */ package practice_01; import

  • 浅谈java中BigDecimal类的简单用法

    一.BigDecimal概述 ​ Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效数,但在实际应用中,可能需要对更大或者更小的数进行运算和处理.一般情况下,对于那些不需要准确计算精度的数字,我们可以直接使用Float和Double处理,但是Double.valueOf(String) 和Float.valueOf(String)会丢失精度.所以开发中,如果我们需要精确计算的结果,则必须使用

  • 详解java中BigDecimal精度问题

    一.背景 在实际开发中,对于 不需要任何准确计算精度的属性可以直接使用float或double,但是如果需要精确计算结果,则必须使用BigDecimal,例如价格.质量. 为什么这么说,主要有两点 1.double计算会有精度丢失问题 2.在除法运算时,BigDecimal提供了丰富的取舍规则.(double虽然可以通过NumberFormat进行四舍五入,但是NumberFormat是线程不安全的) 对于精度问题我们可以看下实际的例子 public static void main(Strin

  • Java之BigDecimal的坑及解决

    目录 Java BigDecimal的坑 采坑处 原因是 解决方式 BigDecimal容易出现的坑 Java BigDecimal的坑 采坑处 BigDecimal bd =new BigDecimal(0.1); System.out.println("结果是:" + bd); 结果是:158.740000000000009094947017729282379150390625 原因是 1)参数类型为double的构造方法的结果有一定的不可预知性.有人可能认为在Java中写入new

  • Java使用BigDecimal进行运算封装的实际案例

    日常对于金额计算,应该都是用的BigDecimal,可是苦于没有好的工具类方法,现在贡献一个我正在用的对于数字计算的工具类,项目中就是用的这个,简单粗暴好用,话不多说,代码奉上(该工具类需要引入google的一个jar,com.google.common.base.Optional,具体maven引入看文章末尾): import java.math.BigDecimal; public class NumberArithmeticUtils { /** * BigDecimal的加法运算封装 *

  • java中BigDecimal用法详解

    首先,学习一个东西,我们都必须要带着问题去学,这边我分为 [为什么?][是什么?][怎么用?] [为什么要用BigDecimal?] 首先,我们先看一下,下面这个现象 那为什么会出现这种情况呢? 因为不论是float 还是double都是浮点数,而计算机是二进制的,浮点数会失去一定的精确度. 注:根本原因是:十进制值通常没有完全相同的二进制表示形式;十进制数的二进制表示形式可能不精确.只能无限接近于那个值 但是,在项目中,我们不可能让这种情况出现,特别是金融项目,因为涉及金额的计算都必须十分精确

  • 浅谈java中BigDecimal的equals与compareTo的区别

    这两天在处理支付金额校验的时候出现了点问题,有个金额比较我用了BigDecimal的equals方法来比较两个金额是否相等,结果导致金额比较出现错误(比如3.0与3.00的比较等). [注:以下所讲都是以sun jdk 1.4.2版本为例,其他版本实现未必一致,请忽略] 首先看一下BigDecimal的equals方法: public boolean equals(Object x){ if (!(x instanceof BigDecimal)) return false; BigDecima

  • Java中BigDecimal类的简单用法

    本文实例讲述了Java中BigDecimal类的简单用法,是Java程序设计中非常实用的技巧,分享给大家供大家参考.具体用法分析如下: 一般来说,一提到Java里面的商业计算,我们都知道不能用float和double,因为他们无法进行精确计算.但是Java的设计者给编程人员提供了一个很有用的类BigDecimal,他可以完善float和double类无法进行精确计算的缺憾.BigDecimal类位于java.maths类包下.首先我们来看下如何构造一个BigDecimal对象.它的构造函数很多,

随机推荐