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