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对象,几乎没有什么需要分析的,很简单大家可以自己看一看

 

转载于:https://www.cnblogs.com/flydoging/p/10431981.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值