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);
}
}