一、初始化
decimal 的初始化方式有四种
1、new decimal(int);
2、new decimal(long);
3、new decimal(double);会有精度丢失的风险;使用BigDecimal d= BigDecimal.valueOf(double);初始化double
4、new decimal(String);小数最好使用字符初始化
二、计算方式
//加法
BigDecimal r1= v1.add(v2);
//减法
BigDecimal r2= v1.subtract(v2);
//乘法
BigDecimal r3= v1.multiply(v2);
//除法
BigDecimal r4= v1.divide(v2);
三、为什么decimal中不能使用equal进行值比较,而是使用compareTo?
首先肯定是不会用==这种方式来使用哦,这个应该不用多说吧,BigDecimal属于对象,不是基本类型,不能用==来比较
BigDecimal r1= new BigDecimal(10);
BigDecimal r2 = new BigDecimal(10);
System.out.println(r1.equals(r2));
BigDecimal r3= new BigDecimal(10);
BigDecimal r4= new BigDecimal(10.000);
System.out.println(r3.equals(r4));
BigDecimal r5= new BigDecimal("10");
BigDecimal r6= new BigDecimal("10.000");
System.out.println(r5.equals(r6));
以上代码输出结果:true true false
针对equal对比为什么r1与r2是ture的,r3与r4也是ture,r5与r6是false
在源码中有一段
public class BigDecimal extends Number implements Comparable<BigDecimal> {
private final BigInteger intVal;
private final int scale;
private final transient long intCompact;
/**省略代码**/
public boolean equals(Object x) {
if (!(x instanceof BigDecimal))
return false;
BigDecimal xDec = (BigDecimal) x;
if (x == this)
return true;
if (scale != xDec.scale)
return false;
long s = this.intCompact;
long xs = xDec.intCompact;
if (s != INFLATED) {
if (xs == INFLATED)
xs = compactValFor(xDec.intVal);
return xs == s;
} else if (xs != INFLATED)
return xs == compactValFor(this.intVal);
return this.inflated().equals(xDec.inflated());
}
equals不仅会比较数值,还会比较这个标度是否一样,也就是说equals会比较俩个参数,r5与r6的数值一样,但是scale不一样。而compareTo()这个方法只比较数值不比较scale标度。
然后我们来了解一下什么是scale:
如果scale为零或正值,则该值表示这个数字小数点右侧的位数。如果scale为负数,则该数字的真实值需要乘以10的该负数的绝对值的幂。例如,scale为-3,则这个数需要乘1000,即在末尾有3个0。
在BigDecimal有四种定义的类型,包括int、long、double、String四种,首先int和long类型都是整数,标度都是0。当类型是double的时候,new Bigdecimal(double) => new BigDecimale(0.1),实际传入的是0.1000000000000000055511151231527827021181583404541015625,这个时候的标度就是55,也就是小数点的个数。
而对于 new bigDecimal(1.0)来说,实际上就是整数,也就是不存在后缀,所以和整数的标度大小是一样的使用r3与r4为ture
四、最后了解
了解一下
实际上一个BigDecimal是通过一个”无标度值”和一个”标度”来表示一个数的。
而无标度值的表示比较复杂。当unscaled value超过阈值(默认为Long.MAX_VALUE)时采用intVal字段存储unscaled value,intCompact字段存储Long.MIN_VALUE,否则对unscaled value进行压缩存储到long型的intCompact字段用于后续计算,intVal为空。
里面有一个scale标度的比较,大概这就是为什么r5和r6的比较结果是false的原因了。
五、放一个decimal的工具类
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* @create: 2019-04-18 18:19
**/
public class BigDecimalUtil {
public final static BigDecimal NEGATIVE_ONE = new BigDecimal(-1);
public final static BigDecimal HUNDRED = new BigDecimal("100");
public final static BigDecimal TEN_THOUSAND = new BigDecimal("10000");
/**
* 获取该数的相反数
* @param number 需要转换的数字
* @return java.math.BigDecimal
* @date 2019/4/18 18:22
*/
public static BigDecimal getOppositeNumber(BigDecimal number){
return notNull(number).multiply(NEGATIVE_ONE);
}
/**
* 两数相减
* @param v1 被减数
* @param v2 减数
* @return java.math.BigDecimal
* @date 2019/4/18 18:26
*/
public static BigDecimal subtraction(BigDecimal v1, BigDecimal v2){
return notNull(v1).subtract(notNull(v2));
}
/**
* 两数相加
* @param v1 加数1
* @param v2 加数2
* @return java.math.BigDecimal
* @date 2019/4/18 18:26
*/
public static BigDecimal addition(BigDecimal v1, BigDecimal v2){
return notNull(v1).add(notNull(v2));
}
/**
* 两数相除
* @param v1 被除数
* @param v2 除数
* @param scale 保留小数位
* @return java.math.BigDecimal
* @date 2020/1/6 17:24
*/
public static BigDecimal division(BigDecimal v1, BigDecimal v2, int scale){
return division(v1, v2, scale, BigDecimal.ROUND_HALF_UP);
}
/**
* 两数相除
* @param v1 被除数
* @param v2 除数
* @param scale 保留小数位
* @param roundingMode 保留模式
* @return java.math.BigDecimal
* @date 2021/4/15 17:09
*/
public static BigDecimal division(BigDecimal v1, BigDecimal v2, int scale, int roundingMode){
return notNull(v1).divide(notNull(v2), scale, roundingMode);
}
/**
* 如果除数为null或为0,则返回0
* @param v1 被除数
* @param v2 除数
* @param scale 保留小数位
* @return java.math.BigDecimal
* @date 2020/3/2 11:56
*/
public static BigDecimal divisionIgnoreZero(BigDecimal v1, BigDecimal v2, int scale){
if (BigDecimalUtil.isEqualsZero(notNull(v2))){
return BigDecimal.ZERO;
}
return BigDecimalUtil.division(v1, v2, scale);
}
/**
* 两数相乘
* @param v1 被乘数
* @param v2 乘数
* @param scale 保留小数位
* @return java.math.BigDecimal
* @date 2020/1/6 17:24
*/
public static BigDecimal multiply(BigDecimal v1, BigDecimal v2, int scale){
return notNull(v1).multiply(notNull(v2)).setScale(scale, RoundingMode.HALF_UP);
}
/**
* 是否大于等于0
* @param v 需要判断的值
* @return boolean true:是;false:否
* @date 2019/4/19 11:15
*/
public static boolean isGreaterAndEqualsZero(BigDecimal v){
int r = notNull(v).compareTo(BigDecimal.ZERO);
return r > 0 || r == 0;
}
/**
* v1是否大于等于v2
* @param v1 左边的值
* @param v2 右边的值
* @return boolean true:是;false:否
* @date 2019/4/19 11:15
*/
public static boolean isGreaterAndEquals(BigDecimal v1, BigDecimal v2){
int r = notNull(v1).compareTo(notNull(v2));
return r > 0 || r == 0;
}
/**
* v1是否大于v2
* @param v1 左边的值
* @param v2 右边的值
* @return boolean true:是;false:否
* @date 2021/4/22 14:53
*/
public static boolean isGreater(BigDecimal v1, BigDecimal v2){
int r = notNull(v1).compareTo(notNull(v2));
return r > 0;
}
/**
* v1是否等于0
* @param v1 需比较的值
* @return boolean true:是;false:否
* @date 2019/4/19 17:12
*/
public static boolean isEqualsZero(BigDecimal v1){
int r = notNull(v1).compareTo(BigDecimal.ZERO);
return r == 0;
}
/**
* v1是否大于0
* @param v1 需比较的值
* @return boolean true:是;false:否
* @date 2019/4/19 17:12
*/
public static boolean isGreaterZero(BigDecimal v1){
int r = notNull(v1).compareTo(BigDecimal.ZERO);
return r > 0;
}
/**
* v1是否等于v2
* @param v1 左边的值
* @param v2 右边的值
* @return boolean true:是;false:否
* @date 2019/6/10 16:52
*/
public static boolean isEquals(BigDecimal v1, BigDecimal v2){
int r = notNull(v1).compareTo(notNull(v2));
return r == 0;
}
/**
* 得到该数的正数
* @param v 需要转换的数字
* @return java.math.BigDecimal
* @date 2019/6/12 14:41
*/
public static BigDecimal getPositiveNumber(BigDecimal v){
if (!isGreaterZero(v)){
return getOppositeNumber(v);
}
return v;
}
/**
* 得到该数的负数
* @param v 需要转换的数字
* @return java.math.BigDecimal
* @date 2019/6/12 14:41
*/
public static BigDecimal getNegativeNumber(BigDecimal v){
if (isGreaterZero(v)){
return getOppositeNumber(v);
}
return v;
}
/**
* 获取非空的BigDecimal对象,为null则返回0
* @param value 需要判断的值
* @return java.math.BigDecimal 非空的BigDecimal对象
* @date 2019/12/25 10:28
*/
public static BigDecimal notNull(BigDecimal value){
if (value == null) {
return BigDecimal.ZERO;
}
return value;
}
/**
* 获取两个数中比较小的值
* @param v1 第一个值
* @param v2 第二个值
* @return java.math.BigDecimal 比较小的值
* @date 2021/7/8 16:02
*/
public static BigDecimal getLeast(BigDecimal v1, BigDecimal v2){
return notNull(v1).compareTo(notNull(v2)) > 0? v2: v1;
}
/**
* 获取两个数中比较大的值
* @param v1 第一个值
* @param v2 第二个值
* @return java.math.BigDecimal 比较大的值
* @date 2021-07-20 17:35
*/
public static BigDecimal getBigger(BigDecimal v1, BigDecimal v2){
return notNull(v1).compareTo(notNull(v2)) > 0? v1: v2;
}
/**
* 获取百分比
*
* @param v 需要转换为百分比的值
* @param scale 规模
* @return {@link BigDecimal }
* @date 2021-10-11 15:32:49
*/
public static BigDecimal getPercentage(BigDecimal v, int scale){
return BigDecimalUtil.multiply(v, HUNDRED, scale);
}
private BigDecimalUtil(){
}
}