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