package org.lee.study.utils;
import java.math.BigDecimal;
/**
* 用于高精度的数学运算
* 1.加减乘除
* 2.四舍五入
* 3.比较大小
*
* BigDecimal类:
* 优点:适合精确的小数点计算。
* 缺点:性能差。
* 使用:开发过程一般使用String的构造函数。
* @author lee
* @date 2022/4/21 14:25
*/
public class ArithmeticUtils {
private static final int DEF_DIV_SCALE = 10;
/**
* double类型的加法运算(不会丢失精度)
* 通过源码可知,String.valueOf(double d)等同于Double.toString(d);
* @param v1 被加数
* @param v2 加数
* @return 相加之和
*/
public static double add(double v1, double v2){
BigDecimal b1 = new BigDecimal(String.valueOf(v1));
BigDecimal b2 = new BigDecimal(String.valueOf(v2));
return b1.add(b2).doubleValue();
}
/**
* String类型的加法运算(不会丢失精度)
* @param v1 被加数
* @param v2 加数
* @return 相加之和
*/
public static BigDecimal add(String v1, String v2){
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.add(b2);
}
/**
* String类型保留小数点的加法运算
* BigDecimal.ROUND_HALF_UP等同于四舍五入
* @param v1 被加数
* @param v2 加数
* @param scale 保留小数点位数
* @return 相加之和 subtraction
*/
public static String add(String v1, String v2, int scale){
if(scale < 0){
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.add(b2).setScale(scale,BigDecimal.ROUND_HALF_UP).toString();
}
/**
* double类型的减法运算(不会丢失精度)
* @param v1 被减数
* @param v2 减数
* @return 相减之差
*/
public static double subtraction(double v1, double v2){
BigDecimal b1 = new BigDecimal(String.valueOf(v1));
BigDecimal b2 = new BigDecimal(String.valueOf(v2));
return b1.subtract(b2).doubleValue();
}
/**
* String类型的减法运算(不会丢失精度)
* @param v1 被减数
* @param v2 减数
* @return 相减之差
*/
public static BigDecimal subtraction(String v1, String v2){
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.subtract(b2);
}
/**
* String类型保留小数点的减法运算
* BigDecimal.ROUND_HALF_UP等同于四舍五入
* @param v1 被减数
* @param v2 减数
* @param scale 保留小数点位数
* @return 相减之差
*/
public static String subtraction(String v1, String v2, int scale){
if(scale < 0){
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.subtract(b2).setScale(scale,BigDecimal.ROUND_HALF_UP).toString();
}
/**
* double类型的乘法运算(不会丢失精度)
* @param v1 乘数
* @param v2 乘数
* @return 乘积
*/
public static double multiplication(double v1, double v2){
BigDecimal b1 = new BigDecimal(String.valueOf(v1));
BigDecimal b2 = new BigDecimal(String.valueOf(v2));
return b1.multiply(b2).doubleValue();
}
/**
* String类型的乘法运算(不会丢失精度)
* @param v1 乘数
* @param v2 乘数
* @return 乘积
*/
public static BigDecimal multiplication(String v1, String v2){
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.multiply(b2);
}
/**
* String类型保留小数点的乘法运算
* BigDecimal.ROUND_HALF_UP等同于四舍五入
* @param v1 乘数
* @param v2 乘数
* @param scale 保留小数点位数
* @return 乘积
*/
public static String multiplication(String v1, String v2, int scale){
if(scale < 0){
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.multiply(b2).setScale(scale,BigDecimal.ROUND_HALF_UP).toString();
}
/**
* double类型保留小数点的除法运算
* @param v1 被除数
* @param v2 除数
* @return 商
*/
private static double division(double v1, double v2){
return division(v1,v2,DEF_DIV_SCALE);
}
/**
* double类型保留小数点的除法运算
* @param v1 被除数
* @param v2 除数
* @param scale 保留的小数点数
* @return 商
*/
public static double division(double v1, double v2, int scale){
if(scale < 0){
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(String.valueOf(v1));
BigDecimal b2 = new BigDecimal(String.valueOf(v2));
return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 四舍五入处理
* @param v 需要四舍五入的值
* @param scale 小数点后的值
* @return 四舍五入后的值
*/
public static double round(double v, int scale){
if(scale < 0){
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(String.valueOf(v));
return b.setScale(scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
/**
* 四舍五入处理
* @param v 需要四舍五入的值
* @param scale 保留小数点的位数
* @return 四舍五入后的值
*/
public static String round(String v, int scale){
if(scale < 0){
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(v);
return b.setScale(scale,BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 取余数
* @param v1 被除数
* @param v2 除数
* @param scale 保留小数点的位数
* @return 余数
*/
public static String remainder(String v1, String v2, int scale){
if(scale < 0){
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
return b1.remainder(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 取余数
* @param v1 被除数
* @param v2 除数
* @param scale 保留小数点的位数
* @return 余数
*/
public static String remainder(BigDecimal v1, BigDecimal v2, int scale){
if(scale < 0){
throw new IllegalArgumentException("The scale must be a positive integer or zero");
}
return v1.remainder(v2).setScale(scale, BigDecimal.ROUND_HALF_UP).toString();
}
/**
* 比较大小
* a = -1,表示v1小于v2
* a = 0,表示v1等于v2
* a = 1,表示v1大于v2
* @param v1 被比较数
* @param v2 比较数
* @return 比较结果 true or false 如果v1大于v2,则返回true,否则返回false
*/
public static boolean compare(String v1, String v2){
BigDecimal b1 = new BigDecimal(v1);
BigDecimal b2 = new BigDecimal(v2);
int bj = b1.compareTo(b2);
boolean res;
if(bj>0) {
res = true;
}
else {
res = false;
}
return res;
}
}
package org.lee.study;
import java.math.BigDecimal;
import java.text.NumberFormat;
/**
* @author lee
* @date 2022/4/21 15:26
*/
public class BigDecimalDemo {
public static void main(String[] args) {
NumberFormat currency = NumberFormat.getCurrencyInstance();
//送参数指定国家币种 Locale.FRANCE,默认是人民币
NumberFormat percent = NumberFormat.getPercentInstance();
percent.setMaximumFractionDigits(3);
BigDecimal loanAmount = new BigDecimal("15000.48");
BigDecimal interestRate = new BigDecimal("0.008");
BigDecimal interest = loanAmount.multiply(interestRate);
System.out.println("贷款金额:\t" + currency.format(loanAmount));
System.out.println("利率:\t" + percent.format(interestRate));
System.out.println("利息:\t" + currency.format(interest));
}
}
package org.lee.study.utils;
import java.text.DecimalFormat;
import java.text.NumberFormat;
/**
* @author lee
* @date 2022/4/21 15:43
*/
public class NumberDealUtils {
/**
* 移除数字前面和后面冗余的0,只保留3位小数
*
* @param isFormat 是否需要千位分隔符(,)这种格式输出
* @param num 被处理的数字
* @return 被处理的数字
*/
public static String trimZero(boolean isFormat, double num) {
NumberFormat nf = NumberFormat.getInstance();
if (!isFormat) {
//设置输出格式是否使用“,”分组,默认是使用的
nf.setGroupingUsed(false);
}
return nf.format(num);
}
/**
* 移除数字前面和后面冗余的0
*
* @param isFormat 是否需要千位分隔符(,)这种格式输出
* @param num 被处理的数字
* @param fractionDigit 要保留的小数位数
* @return 被处理的数字
*/
public static String trimZero(boolean isFormat, double num, int fractionDigit) {
NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(fractionDigit);
if (!isFormat) {
//设置输出格式是否使用“,”分组,默认是使用的
nf.setGroupingUsed(false);
}
return nf.format(num);
}
/**
* 指定位数输出,不足补0
* 整数部分如果位数大于需要的位数按实际位数输出
* 小数部分如果大于需要的位数四舍五入
*
* @param num 被处理的数字
* @param integerDigit 整数部分位数
* @param fractionDigit 小数部分位数
* @return 被处理的数字
*/
public static String addZeroFormat(double num, int integerDigit, int fractionDigit) {
StringBuilder rule = new StringBuilder();
if (integerDigit <= 0) {
rule.append("#");
} else {
for (int i = 0; i < integerDigit; i++) {
rule.append("0");
}
}
if (fractionDigit > 0) {
rule.append(".");
for (int i = 0; i < fractionDigit; i++) {
rule.append("0");
}
}
DecimalFormat df = new DecimalFormat(rule.toString());
return df.format(num);
}
/**
* 保留几位小数,不足不补0,小数部分冗余的0也不显示
*
* @param num 被处理的数字
* @param fractionDigit 要保留小数的位数
* @return 被处理的数字
*/
public static String fractionDigitFormat(double num, int fractionDigit) {
NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(fractionDigit);
//设置输出格式是否使用“,”分组,这里不使用
nf.setGroupingUsed(false);
return nf.format(num);
}
}