zoukankan      html  css  js  c++  java
  • decimal相关知识

    一、初始化

    decimal 的初始化方式有四种

    1、new decimal(int);

    2、new decimal(long);

    3、new decimal(dubbo);会有精度丢失的风险;使用BigDecimal d= BigDecimal.valueOf(dubbo);初始化dubbo

    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(){
    
        }
    }
    学有所思,思有所成。
  • 相关阅读:
    FastAdmin 提示框 toastr 改变文字
    FastAdmin 将会员模块升级为基础模块的升级指导
    随笔
    随笔
    c++11 lambda(了解)
    c++11 类型推断
    boost::archive::text_oarchive
    std::ostringstream
    随笔
    随笔1
  • 原文地址:https://www.cnblogs.com/lqh969696/p/15746068.html
Copyright © 2011-2022 走看看