• JDK8 BigDecimal API-创建BigDecimal源码浅析三


    第三篇

    先介绍以BigInteger为构造参数的构造器

     1     public BigDecimal(BigInteger val) {// 根据BigInteger创建BigDecimal对象
     2         scale = 0;// BigInteger为整数因此有效小数位数为0
     3         intVal = val;
     4         intCompact = compactValFor(val);
     5     }
     6     
     7     public BigDecimal(BigInteger unscaledVal, int scale) {// 这个与上一个差不多但是指定了有效小数位数,但是最终的BigDecimal的数值为unscaledVal*10^-scale次方
     8         // Negative scales are now allowed
     9         this.intVal = unscaledVal;
    10         this.intCompact = compactValFor(unscaledVal);
    11         this.scale = scale;
    12     }
    13     
    14     public BigDecimal(BigInteger val, MathContext mc) {// 该方法转发调用下面的构造器
    15         this(val,0,mc);
    16     }
    17        
    18     public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {
    19         long compactVal = compactValFor(unscaledVal);
    20         int mcp = mc.precision;
    21         int prec = 0;
    22         if (mcp > 0) { // do rounding,根据MathContext中的有效位数进行舍去操作,具体解析见第一篇BigDecimal源码解析文章
    23             int mode = mc.roundingMode.oldMode;
    24             if (compactVal == INFLATED) {
    25                 prec = bigDigitLength(unscaledVal);
    26                 int drop = prec - mcp;
    27                 while (drop > 0) {
    28                     scale = checkScaleNonZero((long) scale - drop);
    29                     unscaledVal = divideAndRoundByTenPow(unscaledVal, drop, mode);
    30                     compactVal = compactValFor(unscaledVal);
    31                     if (compactVal != INFLATED) {
    32                         break;
    33                     }
    34                     prec = bigDigitLength(unscaledVal);
    35                     drop = prec - mcp;
    36                 }
    37             }
    38             if (compactVal != INFLATED) {
    39                 prec = longDigitLength(compactVal);
    40                 int drop = prec - mcp;     // drop can't be more than 18
    41                 while (drop > 0) {
    42                     scale = checkScaleNonZero((long) scale - drop);
    43                     compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mode);
    44                     prec = longDigitLength(compactVal);
    45                     drop = prec - mcp;
    46                 }
    47                 unscaledVal = null;
    48             }
    49         }
    50         this.intVal = unscaledVal;
    51         this.intCompact = compactVal;
    52         this.scale = scale;
    53         this.precision = prec;// 若MathContext中的有效位数小于等于0,则BigDecimal中的有效位数置为0
    54     }

    接下来介绍以int类型为构造参数的构造器

     1     public BigDecimal(int val) {// 以int数值来创建BigDecimal对象,int类型为整数则有效小数位数为0
     2         this.intCompact = val;
     3         this.scale = 0;
     4         this.intVal = null;// 此时BigDecimal的数值在int类型的表数范围因此也在long类型的表数范围,所以intVal为null
     5     }
     6     
     7     public BigDecimal(int val, MathContext mc) {// 该构造器在以int类型为参数的同时传入一个MathContext来限制有效位数
     8         int mcp = mc.precision;
     9         long compactVal = val;
    10         int scale = 0;
    11         int prec = 0;
    12         if (mcp > 0) { // do rounding,根据val的位数与MathContext的有效位数修正最终值的有效位数,即进行舍去操作,具体分析见第一篇BigDecimal源码分析文章
    13             prec = longDigitLength(compactVal);
    14             int drop = prec - mcp; // drop can't be more than 18
    15             while (drop > 0) {
    16                 scale = checkScaleNonZero((long) scale - drop);
    17                 compactVal = divideAndRound(compactVal, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
    18                 prec = longDigitLength(compactVal);
    19                 drop = prec - mcp;
    20             }
    21         }
    22         this.intVal = null;
    23         this.intCompact = compactVal;// BigDecimal对象表示数值的简洁值就是int类型参数val
    24         this.scale = scale;
    25         this.precision = prec;
    26     }

    long类型参数的构造器分析

     1     public BigDecimal(long val) {// 以long类型数值来创建BigDecimal对象,long类型为整数则有效小数位数为0
     2         this.intCompact = val;
     3         this.intVal = (val == INFLATED) ? INFLATED_BIGINT : null;// 若val的数值为long类型最小值需要特殊处理,因为此时的val有特殊含义(数值在long类型下溢出)
     4         this.scale = 0;
     5     }
     6 
     7     public BigDecimal(long val, MathContext mc) {// 该构造器在以long类型为参数的同时传入一个MathContext来限制有效位数
     8         int mcp = mc.precision;
     9         int mode = mc.roundingMode.oldMode;
    10         int prec = 0;
    11         int scale = 0;
    12         BigInteger intVal = (val == INFLATED) ? INFLATED_BIGINT : null;
    13         if (mcp > 0) { // do rounding,根据val的位数与MathContext的有效位数修正最终值的有效位数,即进行舍去操作,具体分析见第一篇BigDecimal源码分析文章
    14             if (val == INFLATED) {// 若val为INFLATED即-2^63,该数位数为19,因此初始化有效位数为19
    15                 prec = 19;
    16                 int drop = prec - mcp;
    17                 while (drop > 0) {
    18                     scale = checkScaleNonZero((long) scale - drop);
    19                     intVal = divideAndRoundByTenPow(intVal, drop, mode);
    20                     val = compactValFor(intVal);
    21                     if (val != INFLATED) {
    22                         break;
    23                     }
    24                     prec = bigDigitLength(intVal);
    25                     drop = prec - mcp;
    26                 }
    27             }
    28             if (val != INFLATED) {
    29                 prec = longDigitLength(val);
    30                 int drop = prec - mcp;
    31                 while (drop > 0) {
    32                     scale = checkScaleNonZero((long) scale - drop);
    33                     val = divideAndRound(val, LONG_TEN_POWERS_TABLE[drop], mc.roundingMode.oldMode);
    34                     prec = longDigitLength(val);
    35                     drop = prec - mcp;
    36                 }
    37                 intVal = null;
    38             }
    39         }
    40         this.intVal = intVal;
    41         this.intCompact = val;
    42         this.scale = scale;
    43         this.precision = prec;
    44     }

    BigDecimal的原码接下来是一堆的静态方法用于创建BigDecimal对象,几乎没有什么需要分析的,很简单大家可以自己看一看

  • 相关阅读:
    hadoop集群部署入门(传智Hadoop学习)
    遇到问题了!
    MD5和TreeView的学习
    今天晚上完成了一个登录功能
    第一次来到博客园!
    单元测试--测?
    单元测试-公司实习1
    Mariadb数据库小结
    [奋斗的人生] 学习,总结,感恩,回馈
    将博客搬至CSDN
  • 原文地址:https://www.cnblogs.com/flydoging/p/10431981.html
Copyright © 2020-2023  润新知