package com.knowledge.system.bigdecimalutil;
import java.math.BigDecimal;
/**
* @program: demo-pom
* @description: BigDecimal工具类
* @author: bo.hu
* @create: 2020-01-14 17:23
**/
public class BigdcmUtil {
/**
* BigDecimal.ROUND_HALF_UP 四舍五入
* BigDecimal.ROUND_HALF_DOWN 五舍六入
* BigDecimal.ROUND_HALF_EVEN 四舍六入,五分两种情况,前一位为奇数,则入位,否则舍去。
*
* BigDecimal.ROUND_DOWN 直接舍弃 ----此舍入模式始终不会增加计算值的大小
* -3.559->-3.55 -3.551->-3.55 3.559->3.55 3.551->3.55
*
* BigDecimal.ROUND_UP 非零直接进位 ----此舍入模式始终不会减少计算值的大小
* -3.550->-3.55 -3.559->-3.56 -3.551->-3.56 3.550->3.55 3.559->3.56 3.551->3.56
*
* BigDecimal.ROUND_CEILING 正--BigDecimal.ROUND_UP,负数--BigDecimal.ROUND_DOWN ----此舍入模式始终不会减少计算值
* -3.550->-3.55 -3.559->-3.55 -3.551->-3.55 3.550->3.55 3.559->3.56 3.551->3.56
*
* BigDecimal.ROUND_FLOOR 正--BigDecimal.ROUND_DOWN,负数--BigDecimal.ROUND_UP ----此舍入模式始终不会增加计算值
* -3.550->-3.55 -3.559->-3.56 -3.551->-3.56 3.550->3.55 3.559->3.55 3.551->3.55
*
* BigDecimal.ROUND_UNNECESSARY 断言请求的操作具有精确的结果,因此不需要舍入。如果对获得精确结果的操作指定此舍入模式,则抛出ArithmeticException。【一般不用】
*
*/
/**
* 金额简单处理 分转元
*
* @param n1 待处理金额
* @param scale 保留小数位数
* @param remainder 尾数处理方式
* @return
*/
public static BigDecimal getY2F(String n1,int scale,int remainder){
if(null==n1){
return null;
}
BigDecimal num1=new BigDecimal(n1);
return num1.multiply(new BigDecimal("100.00")).setScale(scale,remainder);
}
/**
* 金额简单处理 分转元
*
* @param n1 待处理金额
* @param scale 保留小数位数
* @param remainder 尾数处理方式
* @return
*/
public static BigDecimal getF2Y(String n1, int scale, int remainder) {
if (null == n1) {
return null;
}
BigDecimal num1 = new BigDecimal(n1);
return num1.divide(new BigDecimal("100.00"), scale, remainder);
}
/**
* 求变化率
*
* @param n1 除数
* @param n2 被除数
* @param scale 保留小数位数
* @param remainder 小数尾数处理方法
* @return
*/
public static BigDecimal getChangeRatio(double n1, double n2, int scale, int remainder) {
String num1 = Double.toString(n1);
String num2 = Double.toString(n2);
return getChangeRatio(num1, num2, scale, remainder);
}
/**
* 求变化率
*
* @param n1 除数
* @param n2 被除数
* @param scale 保留小数位数
* @param remainder 小数尾数处理方法
* @return
*/
public static BigDecimal getChangeRatio(long n1, long n2, int scale, int remainder) {
String num1 = Long.toString(n1);
String num2 = Long.toString(n2);
return getChangeRatio(num1, num2, scale, remainder);
}
/**
* 求变化率
*
* @param n1 除数
* @param n2 被除数
* @param scale 保留小数位数
* @param remainder 小数尾数处理方法
* @return
*/
public static BigDecimal getChangeRatio(int n1, int n2, int scale, int remainder) {
String num1 = Integer.toString(n1);
String num2 = Integer.toString(n2);
return getChangeRatio(num1, num2, scale, remainder);
}
/**
* 求变化率
*
* @param n1 除数
* @param n2 被除数
* @param scale 保留小数位数
* @param remainder 小数尾数处理方法
* @return
*/
public static BigDecimal getChangeRatio(String n1, String n2, int scale, int remainder) {
if (null == n1 || null == n2) {
return null;
}
BigDecimal v1 = new BigDecimal(n1);
BigDecimal v2 = new BigDecimal(n2);
return getChangeRatio(v1, v2, scale, remainder);
}
/**
* 求变化率
*
* @param n1 除数
* @param n2 被除数
* @param scale 保留小数位数
* @param remainder 小数尾数处理方法
* @return
*/
public static BigDecimal getChangeRatio(BigDecimal n1, BigDecimal n2, int scale, int remainder) {
if (null == n1 || null == n2) {
return null;
}
BigDecimal v1 = n1.subtract(n2);
return getRatio(v1, n2, scale, remainder);
}
/**
* 求变化率
*
* @param n1 除数
* @param n2 被除数
* @param scale 保留小数位数
* @param remainder 小数尾数处理方法
* @return
*/
public static BigDecimal getRatio(long n1, long n2, int scale, int remainder) {
String str1 = Long.toString(n1);
String str2 = Long.toString(n2);
return getRatio(str1, str2, scale, remainder);
}
/**
* 求变化率
*
* @param n1 除数
* @param n2 被除数
* @param scale 保留小数位数
* @param remainder 小数尾数处理方法
* @return
*/
public static BigDecimal getRatio(int n1, int n2, int scale, int remainder) {
String str1 = Integer.toString(n1);
String str2 = Integer.toString(n2);
return getRatio(str1, str2, scale, remainder);
}
/**
* @param d1 除数
* @param d2 被除数
* @param scale 保留小数位数
* @param remainder 小数尾数处理方法
* @return
*/
public static BigDecimal getRatio(double d1, double d2, int scale, int remainder) {
String str1 = Double.toString(d1);
String str2 = Double.toString(d2);
return getRatio(str1, str2, scale, remainder);
}
/**
* 求百分比
*
* @param n1 除数
* @param n2 被除数
* @param scale 保留小数位数
* @param remainder 小数尾数处理方法
* @return
*/
public static BigDecimal getRatio(String n1, String n2, int scale, int remainder) {
if (null == n1 || null == n2) {
return null;
}
BigDecimal v1 = new BigDecimal(n1);
BigDecimal v2 = new BigDecimal(n2);
return getRatio(v1, v2, scale, remainder);
}
/**
* 求百分比
*
* @param n1 除数
* @param n2 被除数
* @param scale 保留小数位数
* @param remainder 小数尾数处理方法
* @return
*/
public static BigDecimal getRatio(BigDecimal n1, BigDecimal n2, int scale, int remainder) {
if (null == n1 || null == n2) {
return null;
}
if (0 == n2.compareTo(BigDecimal.ZERO)) {
return new BigDecimal(1).setScale(scale);
}
return n1.divide(n2, scale, remainder);
}
/**
* 求两数和
*
* @param n1 加数1
* @param n2 加数2
* @param scale 保留小数位数
* @param remainder 小数位数处理方法
* @return
*/
public static BigDecimal add(String n1, String n2, int scale, int remainder) {
if (null == n1 || null == n2) {
return null;
}
BigDecimal num1 = new BigDecimal(n1);
BigDecimal num2 = new BigDecimal(n2);
return (num1.add(num2)).setScale(scale, remainder);
}
/**
* 求两数差
*
* @param n1 减数
* @param n2 被减数
* @param scale 保留小数位数
* @param remainder 小数位数处理方法
* @return
*/
public static BigDecimal sub(String n1, String n2, int scale, int remainder) {
if (null == n1 || null == n2) {
return null;
}
BigDecimal num1 = new BigDecimal(n1);
BigDecimal num2 = new BigDecimal(n2);
return num1.subtract(num2).setScale(scale, remainder);
}
/**
* 求两数积
*
* @param n1 乘数1
* @param n2 乘数2
* @param scale 保留小数位数
* @param remainder 小数位数处理方法
* @return
*/
public static BigDecimal mul(String n1, String n2, int scale, int remainder) {
if (null == n1 || null == n2) {
return null;
}
BigDecimal num1 = new BigDecimal(n1);
BigDecimal num2 = new BigDecimal(n2);
return num1.multiply(num2).setScale(scale, remainder);
}
/**
* @param n1 除数
* @param n2 被除数
* @param scale 保留小数位数
* @param remainder 小数位数处理方法
* @return
*/
public static BigDecimal div(String n1, String n2, int scale, int remainder) {
if (null == n1 || null == n2) {
return null;
}
BigDecimal num1 = new BigDecimal(n1);
BigDecimal num2 = new BigDecimal(n2);
if (0 == num2.compareTo(BigDecimal.ZERO)) {
throw new RuntimeException("除数不能为零");
}
return num1.divide(num2, scale, remainder);
}
/**
* 设置参数小数位数
*
* @param n1 参数
* @param scale 小数点位数
* @param remainder 尾数处理方式
* @return
*/
public static BigDecimal setPoint(String n1, int scale, int remainder) {
if (null == n1) {
return null;
}
BigDecimal num1 = new BigDecimal(n1);
return num1.setScale(scale, remainder);
}
/**
* 设置参数小数位数
*
* @param n1 参数
* @param scale 小数点位数
* @param remainder 尾数处理方式
* @return
*/
public static BigDecimal setPoint(int n1, int scale, int remainder) {
String num1 = Integer.toString(n1);
return setPoint(num1, scale, remainder);
}
/**
* 设置参数小数位数
*
* @param n1 参数
* @param scale 小数点位数
* @param remainder 尾数处理方式
* @return
*/
public static BigDecimal setPoint(long n1, int scale, int remainder) {
String num1 = Long.toString(n1);
return setPoint(num1, scale, remainder);
}
/**
* 设置参数小数位数
*
* @param n1 参数
* @param scale 小数点位数
* @param remainder 尾数处理方式
* @return
*/
public static BigDecimal setPoint(double n1, int scale, int remainder) {
String num1 = Double.toString(n1);
return setPoint(num1, scale, remainder);
}
/**
* 比较大小,flag取值:==:1 <:2 >:3 <=:4 >=:5 !=:6
*
* @param n1
* @param n2
* @param flag
* @return
*/
public static boolean compare(String n1, String n2, int flag) {
if (null == n1 || null == n2 || n1.equals("") || n2.equals("")) {
return false;
}
BigDecimal num1Bcm1 = new BigDecimal(n1);
BigDecimal num2Bcm2 = new BigDecimal(n2);
if (1 == flag) {
return num1Bcm1.compareTo(num2Bcm2) == 0;
}
if (2 == flag) {
return num1Bcm1.compareTo(num2Bcm2) == -1;
}
if (3 == flag) {
return num1Bcm1.compareTo(num2Bcm2) == 1;
}
if (4 == flag) {
return num1Bcm1.compareTo(num2Bcm2) <= 0;
}
if (5 == flag) {
return num1Bcm1.compareTo(num2Bcm2) >= 0;
}
if (6 == flag) {
return !(num1Bcm1.compareTo(num2Bcm2) == 0);
}
return false;
}
public static void main(String[] args) {
/**
* 为什么要使用BigDecimal 深坑1:9.86->9.85 1219.86->121985 精度问题
*/
//+++++++++++Float Double带来的---精度问题++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
System.out.println(0.05 + 0.01);
System.out.println(1.0 - 0.42);
System.out.println(4.015 * 100);
System.out.println(123.3 / 100);
//很有可能造成我们手中有0.06元,却无法购买一个0.05元和一个0.01元的商品。因为如上所示,他们两个的总和为0.060000000000000005。
//float和double只能用来做科学计算和工程计算。商业运算中我们要使用BigDecimal。
//++++++++++++BigDecimal因为创建方式而带来的---精度问题+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
BigDecimal d1 = new BigDecimal(0.6);
BigDecimal d2 = new BigDecimal(0.4);
// BigDecimal d3=d1.divide(d2);//除不尽,精度未设置,导致异常
BigDecimal d7 = d1.divide(d2, 2, BigDecimal.ROUND_HALF_UP);
BigDecimal d4 = new BigDecimal("0.600000");//构造完,自带精度6
BigDecimal d5 = new BigDecimal("4");
BigDecimal d6 = d4.divide(d5);
System.out.println(d6);
System.out.println(d7);
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++商业解决方案:1.无论使用哪种方式创建对象,均指定计算完成后的精度++++++++++++++++++++
//+++++++++++++++++商业解决方案:与之配套的数据库字段设计方案++++++++++++++++++++
//+++++++++++++++++`balance` decimal(18,2) DEFAULT '0.00' COMMENT '账户余额' 默认值一定设置成0.00以免排序时带来类型转换的麻烦
BigDecimal dT1 = new BigDecimal(0.6);
BigDecimal dT2 = new BigDecimal(0.4);
BigDecimal dT3 = dT1.divide(dT2, 2, BigDecimal.ROUND_HALF_UP);
}
}