decimal相关知识

  • Post author:
  • Post category:其他


一、初始化

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(){

    }
}



版权声明:本文为qq_39130650原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。